aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-01-29 23:33:12 -0500
committerAndrew Kelley <andrew@ziglang.org>2020-01-29 23:33:12 -0500
commita95dce15ae4bd95cfd2266da51ba860cc6524a1b (patch)
treee761ecb74f37ff699d2e1f09d122811b101826e4 /lib/std
parent800ead2810fa573a7e94979e707a14d4e066ef77 (diff)
parent7ebc624a15c5a01d6bee8eaf9c7487b30ed1904c (diff)
downloadzig-a95dce15ae4bd95cfd2266da51ba860cc6524a1b.tar.gz
zig-a95dce15ae4bd95cfd2266da51ba860cc6524a1b.zip
Merge remote-tracking branch 'origin/master' into llvm10
Diffstat (limited to 'lib/std')
-rw-r--r--lib/std/buffer.zig6
-rw-r--r--lib/std/build.zig50
-rw-r--r--lib/std/builtin.zig24
-rw-r--r--lib/std/c.zig6
-rw-r--r--lib/std/c/ast.zig681
-rw-r--r--lib/std/c/darwin.zig3
-rw-r--r--lib/std/c/parse.zig1431
-rw-r--r--lib/std/c/tokenizer.zig1583
-rw-r--r--lib/std/debug.zig1071
-rw-r--r--lib/std/fmt.zig5
-rw-r--r--lib/std/fmt/parse_float.zig4
-rw-r--r--lib/std/hash/murmur.zig6
-rw-r--r--lib/std/http/headers.zig2
-rw-r--r--lib/std/io/out_stream.zig12
-rw-r--r--lib/std/io/test.zig4
-rw-r--r--lib/std/math/fabs.zig4
-rw-r--r--lib/std/math/isinf.zig12
-rw-r--r--lib/std/math/isnan.zig4
-rw-r--r--lib/std/mem.zig3
-rw-r--r--lib/std/meta.zig18
-rw-r--r--lib/std/os.zig2
-rw-r--r--lib/std/os/linux.zig57
-rw-r--r--lib/std/os/linux/tls.zig2
-rw-r--r--lib/std/os/test.zig3
-rw-r--r--lib/std/sort.zig16
-rw-r--r--lib/std/special/compiler_rt.zig1
-rw-r--r--lib/std/special/compiler_rt/addXf3_test.zig8
-rw-r--r--lib/std/special/compiler_rt/fixtfdi_test.zig4
-rw-r--r--lib/std/special/compiler_rt/fixtfsi_test.zig4
-rw-r--r--lib/std/special/compiler_rt/fixtfti_test.zig4
-rw-r--r--lib/std/special/compiler_rt/fixunstfdi_test.zig4
-rw-r--r--lib/std/special/compiler_rt/fixunstfsi_test.zig4
-rw-r--r--lib/std/special/compiler_rt/fixunstfti_test.zig4
-rw-r--r--lib/std/special/compiler_rt/floattitf_test.zig4
-rw-r--r--lib/std/special/compiler_rt/floatuntitf_test.zig4
-rw-r--r--lib/std/special/compiler_rt/int.zig60
-rw-r--r--lib/std/special/compiler_rt/mulXf3_test.zig4
-rw-r--r--lib/std/special/compiler_rt/truncXfYf2_test.zig8
-rw-r--r--lib/std/target.zig380
-rw-r--r--lib/std/target/aarch64.zig1450
-rw-r--r--lib/std/target/amdgpu.zig1315
-rw-r--r--lib/std/target/arm.zig2333
-rw-r--r--lib/std/target/avr.zig2380
-rw-r--r--lib/std/target/bpf.zig76
-rw-r--r--lib/std/target/hexagon.zig312
-rw-r--r--lib/std/target/mips.zig518
-rw-r--r--lib/std/target/msp430.zig72
-rw-r--r--lib/std/target/nvptx.zig309
-rw-r--r--lib/std/target/powerpc.zig938
-rw-r--r--lib/std/target/riscv.zig122
-rw-r--r--lib/std/target/sparc.zig495
-rw-r--r--lib/std/target/systemz.zig510
-rw-r--r--lib/std/target/wasm.zig114
-rw-r--r--lib/std/target/x86.zig2859
54 files changed, 18594 insertions, 711 deletions
diff --git a/lib/std/buffer.zig b/lib/std/buffer.zig
index 6313d693b7..42bf8e8142 100644
--- a/lib/std/buffer.zig
+++ b/lib/std/buffer.zig
@@ -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 {
diff --git a/lib/std/build.zig b/lib/std/build.zig
index 53f8f19df5..f535b022af 100644
--- a/lib/std/build.zig
+++ b/lib/std/build.zig
@@ -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());
+ }
},
}
diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig
index 55f044094e..d8f24753d3 100644
--- a/lib/std/builtin.zig
+++ b/lib/std/builtin.zig
@@ -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 {
diff --git a/lib/std/c.zig b/lib/std/c.zig
index c912c72418..4d5e72f502 100644
--- a/lib/std/c.zig
+++ b/lib/std/c.zig
@@ -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) {
diff --git a/lib/std/c/ast.zig b/lib/std/c/ast.zig
new file mode 100644
index 0000000000..bb8c01f138
--- /dev/null
+++ b/lib/std/c/ast.zig
@@ -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 {};
+ };
+};
diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig
index bc58b1fba1..524c82211e 100644
--- a/lib/std/c/darwin.zig
+++ b/lib/std/c/darwin.zig
@@ -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;
diff --git a/lib/std/c/parse.zig b/lib/std/c/parse.zig
new file mode 100644
index 0000000000..dd646e06d6
--- /dev/null
+++ b/lib/std/c/parse.zig
@@ -0,0 +1,1431 @@
+const std = @import("std");
+const mem = std.mem;
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const ast = std.c.ast;
+const Node = ast.Node;
+const Type = ast.Type;
+const Tree = ast.Tree;
+const TokenIndex = ast.TokenIndex;
+const Token = std.c.Token;
+const TokenIterator = ast.Tree.TokenList.Iterator;
+
+pub const Error = error{ParseError} || Allocator.Error;
+
+pub const Options = struct {
+ // /// Keep simple macros unexpanded and add the definitions to the ast
+ // retain_macros: bool = false,
+ /// Warning or error
+ warn_as_err: union(enum) {
+ /// All warnings are warnings
+ None,
+
+ /// Some warnings are errors
+ Some: []@TagType(ast.Error),
+
+ /// All warnings are errors
+ All,
+ } = .All,
+};
+
+/// Result should be freed with tree.deinit() when there are
+/// no more references to any of the tokens or nodes.
+pub fn parse(allocator: *Allocator, source: []const u8, options: Options) !*Tree {
+ const tree = blk: {
+ // This block looks unnecessary, but is a "foot-shield" to prevent the SegmentedLists
+ // from being initialized with a pointer to this `arena`, which is created on
+ // the stack. Following code should instead refer to `&tree.arena_allocator`, a
+ // pointer to data which lives safely on the heap and will outlive `parse`.
+ var arena = std.heap.ArenaAllocator.init(allocator);
+ errdefer arena.deinit();
+ const tree = try arena.allocator.create(ast.Tree);
+ tree.* = .{
+ .root_node = undefined,
+ .arena_allocator = arena,
+ .tokens = undefined,
+ .sources = undefined,
+ };
+ break :blk tree;
+ };
+ errdefer tree.deinit();
+ const arena = &tree.arena_allocator.allocator;
+
+ tree.tokens = ast.Tree.TokenList.init(arena);
+ tree.sources = ast.Tree.SourceList.init(arena);
+
+ var tokenizer = std.zig.Tokenizer.init(source);
+ while (true) {
+ const tree_token = try tree.tokens.addOne();
+ tree_token.* = tokenizer.next();
+ if (tree_token.id == .Eof) break;
+ }
+ // TODO preprocess here
+ var it = tree.tokens.iterator(0);
+
+ while (true) {
+ const tok = it.peek().?.id;
+ switch (id) {
+ .LineComment,
+ .MultiLineComment,
+ => {
+ _ = it.next();
+ },
+ else => break,
+ }
+ }
+
+ var parse_arena = std.heap.ArenaAllocator.init(allocator);
+ defer parse_arena.deinit();
+
+ var parser = Parser{
+ .scopes = Parser.SymbolList.init(allocator),
+ .arena = &parse_arena.allocator,
+ .it = &it,
+ .tree = tree,
+ .options = options,
+ };
+ defer parser.symbols.deinit();
+
+ tree.root_node = try parser.root();
+ return tree;
+}
+
+const Parser = struct {
+ arena: *Allocator,
+ it: *TokenIterator,
+ tree: *Tree,
+
+ arena: *Allocator,
+ scopes: ScopeList,
+ options: Options,
+
+ const ScopeList = std.SegmentedLists(Scope);
+ const SymbolList = std.SegmentedLists(Symbol);
+
+ const Scope = struct {
+ kind: ScopeKind,
+ syms: SymbolList,
+ };
+
+ const Symbol = struct {
+ name: []const u8,
+ ty: *Type,
+ };
+
+ const ScopeKind = enum {
+ Block,
+ Loop,
+ Root,
+ Switch,
+ };
+
+ fn pushScope(parser: *Parser, kind: ScopeKind) !void {
+ const new = try parser.scopes.addOne();
+ new.* = .{
+ .kind = kind,
+ .syms = SymbolList.init(parser.arena),
+ };
+ }
+
+ fn popScope(parser: *Parser, len: usize) void {
+ _ = parser.scopes.pop();
+ }
+
+ fn getSymbol(parser: *Parser, tok: TokenIndex) ?*Symbol {
+ const name = parser.tree.tokenSlice(tok);
+ var scope_it = parser.scopes.iterator(parser.scopes.len);
+ while (scope_it.prev()) |scope| {
+ var sym_it = scope.syms.iterator(scope.syms.len);
+ while (sym_it.prev()) |sym| {
+ if (mem.eql(u8, sym.name, name)) {
+ return sym;
+ }
+ }
+ }
+ return null;
+ }
+
+ fn declareSymbol(parser: *Parser, type_spec: Node.TypeSpec, dr: *Node.Declarator) Error!void {
+ return; // TODO
+ }
+
+ /// Root <- ExternalDeclaration* eof
+ fn root(parser: *Parser) Allocator.Error!*Node.Root {
+ try parser.pushScope(.Root);
+ defer parser.popScope();
+ const node = try parser.arena.create(Node.Root);
+ node.* = .{
+ .decls = Node.Root.DeclList.init(parser.arena),
+ .eof = undefined,
+ };
+ while (parser.externalDeclarations() catch |e| switch (e) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.ParseError => return node,
+ }) |decl| {
+ try node.decls.push(decl);
+ }
+ node.eof = parser.eatToken(.Eof) orelse return node;
+ return node;
+ }
+
+ /// ExternalDeclaration
+ /// <- DeclSpec Declarator OldStyleDecl* CompoundStmt
+ /// / Declaration
+ /// OldStyleDecl <- DeclSpec Declarator (COMMA Declarator)* SEMICOLON
+ fn externalDeclarations(parser: *Parser) !?*Node {
+ return parser.declarationExtra(false);
+ }
+
+ /// Declaration
+ /// <- DeclSpec DeclInit SEMICOLON
+ /// / StaticAssert
+ /// DeclInit <- Declarator (EQUAL Initializer)? (COMMA Declarator (EQUAL Initializer)?)*
+ fn declaration(parser: *Parser) !?*Node {
+ return parser.declarationExtra(true);
+ }
+
+ fn declarationExtra(parser: *Parser, local: bool) !?*Node {
+ if (try parser.staticAssert()) |decl| return decl;
+ const begin = parser.it.index + 1;
+ var ds = Node.DeclSpec{};
+ const got_ds = try parser.declSpec(&ds);
+ if (local and !got_ds) {
+ // not a declaration
+ return null;
+ }
+ switch (ds.storage_class) {
+ .Auto, .Register => |tok| return parser.err(.{
+ .InvalidStorageClass = .{ .token = tok },
+ }),
+ .Typedef => {
+ const node = try parser.arena.create(Node.Typedef);
+ node.* = .{
+ .decl_spec = ds,
+ .declarators = Node.Typedef.DeclaratorList.init(parser.arena),
+ .semicolon = undefined,
+ };
+ while (true) {
+ const dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{
+ .ExpectedDeclarator = .{ .token = parser.it.index },
+ }));
+ try parser.declareSymbol(ds.type_spec, dr);
+ try node.declarators.push(&dr.base);
+ if (parser.eatToken(.Comma)) |_| {} else break;
+ }
+ return &node.base;
+ },
+ else => {},
+ }
+ var first_dr = try parser.declarator(.Must);
+ if (first_dr != null and declaratorIsFunction(first_dr.?)) {
+ // TODO typedeffed fn proto-only
+ const dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?);
+ try parser.declareSymbol(ds.type_spec, dr);
+ var old_decls = Node.FnDecl.OldDeclList.init(parser.arena);
+ const body = if (parser.eatToken(.Semicolon)) |_|
+ null
+ else blk: {
+ if (local) {
+ // TODO nested function warning
+ }
+ // TODO first_dr.is_old
+ // while (true) {
+ // var old_ds = Node.DeclSpec{};
+ // if (!(try parser.declSpec(&old_ds))) {
+ // // not old decl
+ // break;
+ // }
+ // var old_dr = (try parser.declarator(.Must));
+ // // if (old_dr == null)
+ // // try parser.err(.{
+ // // .NoParamName = .{ .token = parser.it.index },
+ // // });
+ // // try old_decls.push(decl);
+ // }
+ const body_node = (try parser.compoundStmt()) orelse return parser.err(.{
+ .ExpectedFnBody = .{ .token = parser.it.index },
+ });
+ break :blk @fieldParentPtr(Node.CompoundStmt, "base", body_node);
+ };
+
+ const node = try parser.arena.create(Node.FnDecl);
+ node.* = .{
+ .decl_spec = ds,
+ .declarator = dr,
+ .old_decls = old_decls,
+ .body = body,
+ };
+ return &node.base;
+ } else {
+ switch (ds.fn_spec) {
+ .Inline, .Noreturn => |tok| return parser.err(.{
+ .FnSpecOnNonFn = .{ .token = tok },
+ }),
+ else => {},
+ }
+ // TODO threadlocal without static or extern on local variable
+ const node = try parser.arena.create(Node.VarDecl);
+ node.* = .{
+ .decl_spec = ds,
+ .initializers = Node.VarDecl.Initializers.init(parser.arena),
+ .semicolon = undefined,
+ };
+ if (first_dr == null) {
+ node.semicolon = try parser.expectToken(.Semicolon);
+ const ok = switch (ds.type_spec.spec) {
+ .Enum => |e| e.name != null,
+ .Record => |r| r.name != null,
+ else => false,
+ };
+ const q = ds.type_spec.qual;
+ if (!ok)
+ try parser.warn(.{
+ .NothingDeclared = .{ .token = begin },
+ })
+ else if (q.@"const" orelse q.atomic orelse q.@"volatile" orelse q.restrict) |tok|
+ try parser.warn(.{
+ .QualifierIgnored = .{ .token = tok },
+ });
+ return &node.base;
+ }
+ var dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?);
+ while (true) {
+ try parser.declareSymbol(ds.type_spec, dr);
+ if (parser.eatToken(.Equal)) |tok| {
+ try node.initializers.push((try parser.initializer(dr)) orelse return parser.err(.{
+ .ExpectedInitializer = .{ .token = parser.it.index },
+ }));
+ } else
+ try node.initializers.push(&dr.base);
+ if (parser.eatToken(.Comma) != null) break;
+ dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{
+ .ExpectedDeclarator = .{ .token = parser.it.index },
+ }));
+ }
+ node.semicolon = try parser.expectToken(.Semicolon);
+ return &node.base;
+ }
+ }
+
+ fn declaratorIsFunction(node: *Node) bool {
+ if (node.id != .Declarator) return false;
+ assert(node.id == .Declarator);
+ const dr = @fieldParentPtr(Node.Declarator, "base", node);
+ if (dr.suffix != .Fn) return false;
+ switch (dr.prefix) {
+ .None, .Identifer => return true,
+ .Complex => |inner| {
+ var inner_node = inner.inner;
+ while (true) {
+ if (inner_node.id != .Declarator) return false;
+ assert(inner_node.id == .Declarator);
+ const inner_dr = @fieldParentPtr(Node.Declarator, "base", inner_node);
+ if (inner_dr.pointer != null) return false;
+ switch (inner_dr.prefix) {
+ .None, .Identifer => return true,
+ .Complex => |c| inner_node = c.inner,
+ }
+ }
+ },
+ }
+ }
+
+ /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON
+ fn staticAssert(parser: *Parser) !?*Node {
+ const tok = parser.eatToken(.Keyword_static_assert) orelse return null;
+ _ = try parser.expectToken(.LParen);
+ const const_expr = (try parser.constExpr()) orelse parser.err(.{
+ .ExpectedExpr = .{ .token = parser.it.index },
+ });
+ _ = try parser.expectToken(.Comma);
+ const str = try parser.expectToken(.StringLiteral);
+ _ = try parser.expectToken(.RParen);
+ const node = try parser.arena.create(Node.StaticAssert);
+ node.* = .{
+ .assert = tok,
+ .expr = const_expr,
+ .semicolon = try parser.expectToken(.Semicolon),
+ };
+ return &node.base;
+ }
+
+ /// DeclSpec <- (StorageClassSpec / TypeSpec / FnSpec / AlignSpec)*
+ /// returns true if any tokens were consumed
+ fn declSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
+ var got = false;
+ while ((try parser.storageClassSpec(ds)) or (try parser.typeSpec(&ds.type_spec)) or (try parser.fnSpec(ds)) or (try parser.alignSpec(ds))) {
+ got = true;
+ }
+ return got;
+ }
+
+ /// StorageClassSpec
+ /// <- Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register
+ fn storageClassSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
+ blk: {
+ if (parser.eatToken(.Keyword_typedef)) |tok| {
+ if (ds.storage_class != .None or ds.thread_local != null)
+ break :blk;
+ ds.storage_class = .{ .Typedef = tok };
+ } else if (parser.eatToken(.Keyword_extern)) |tok| {
+ if (ds.storage_class != .None)
+ break :blk;
+ ds.storage_class = .{ .Extern = tok };
+ } else if (parser.eatToken(.Keyword_static)) |tok| {
+ if (ds.storage_class != .None)
+ break :blk;
+ ds.storage_class = .{ .Static = tok };
+ } else if (parser.eatToken(.Keyword_thread_local)) |tok| {
+ switch (ds.storage_class) {
+ .None, .Extern, .Static => {},
+ else => break :blk,
+ }
+ ds.thread_local = tok;
+ } else if (parser.eatToken(.Keyword_auto)) |tok| {
+ if (ds.storage_class != .None or ds.thread_local != null)
+ break :blk;
+ ds.storage_class = .{ .Auto = tok };
+ } else if (parser.eatToken(.Keyword_register)) |tok| {
+ if (ds.storage_class != .None or ds.thread_local != null)
+ break :blk;
+ ds.storage_class = .{ .Register = tok };
+ } else return false;
+ return true;
+ }
+ try parser.warn(.{
+ .DuplicateSpecifier = .{ .token = parser.it.index },
+ });
+ return true;
+ }
+
+ /// TypeSpec
+ /// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double
+ /// / Keyword_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary /
+ /// / Keyword_atomic LPAREN TypeName RPAREN
+ /// / EnumSpec
+ /// / RecordSpec
+ /// / IDENTIFIER // typedef name
+ /// / TypeQual
+ fn typeSpec(parser: *Parser, type_spec: *Node.TypeSpec) !bool {
+ blk: {
+ if (parser.eatToken(.Keyword_void)) |tok| {
+ if (type_spec.spec != .None)
+ break :blk;
+ type_spec.spec = .{ .Void = tok };
+ } else if (parser.eatToken(.Keyword_char)) |tok| {
+ switch (type_spec.spec) {
+ .None => {
+ type_spec.spec = .{
+ .Char = .{
+ .char = tok,
+ },
+ };
+ },
+ .Int => |int| {
+ if (int.int != null)
+ break :blk;
+ type_spec.spec = .{
+ .Char = .{
+ .char = tok,
+ .sign = int.sign,
+ },
+ };
+ },
+ else => break :blk,
+ }
+ } else if (parser.eatToken(.Keyword_short)) |tok| {
+ switch (type_spec.spec) {
+ .None => {
+ type_spec.spec = .{
+ .Short = .{
+ .short = tok,
+ },
+ };
+ },
+ .Int => |int| {
+ if (int.int != null)
+ break :blk;
+ type_spec.spec = .{
+ .Short = .{
+ .short = tok,
+ .sign = int.sign,
+ },
+ };
+ },
+ else => break :blk,
+ }
+ } else if (parser.eatToken(.Keyword_long)) |tok| {
+ switch (type_spec.spec) {
+ .None => {
+ type_spec.spec = .{
+ .Long = .{
+ .long = tok,
+ },
+ };
+ },
+ .Int => |int| {
+ type_spec.spec = .{
+ .Long = .{
+ .long = tok,
+ .sign = int.sign,
+ .int = int.int,
+ },
+ };
+ },
+ .Long => |*long| {
+ if (long.longlong != null)
+ break :blk;
+ long.longlong = tok;
+ },
+ .Double => |*double| {
+ if (double.long != null)
+ break :blk;
+ double.long = tok;
+ },
+ else => break :blk,
+ }
+ } else if (parser.eatToken(.Keyword_int)) |tok| {
+ switch (type_spec.spec) {
+ .None => {
+ type_spec.spec = .{
+ .Int = .{
+ .int = tok,
+ },
+ };
+ },
+ .Short => |*short| {
+ if (short.int != null)
+ break :blk;
+ short.int = tok;
+ },
+ .Int => |*int| {
+ if (int.int != null)
+ break :blk;
+ int.int = tok;
+ },
+ .Long => |*long| {
+ if (long.int != null)
+ break :blk;
+ long.int = tok;
+ },
+ else => break :blk,
+ }
+ } else if (parser.eatToken(.Keyword_signed) orelse parser.eatToken(.Keyword_unsigned)) |tok| {
+ switch (type_spec.spec) {
+ .None => {
+ type_spec.spec = .{
+ .Int = .{
+ .sign = tok,
+ },
+ };
+ },
+ .Char => |*char| {
+ if (char.sign != null)
+ break :blk;
+ char.sign = tok;
+ },
+ .Short => |*short| {
+ if (short.sign != null)
+ break :blk;
+ short.sign = tok;
+ },
+ .Int => |*int| {
+ if (int.sign != null)
+ break :blk;
+ int.sign = tok;
+ },
+ .Long => |*long| {
+ if (long.sign != null)
+ break :blk;
+ long.sign = tok;
+ },
+ else => break :blk,
+ }
+ } else if (parser.eatToken(.Keyword_float)) |tok| {
+ if (type_spec.spec != .None)
+ break :blk;
+ type_spec.spec = .{
+ .Float = .{
+ .float = tok,
+ },
+ };
+ } else if (parser.eatToken(.Keyword_double)) |tok| {
+ if (type_spec.spec != .None)
+ break :blk;
+ type_spec.spec = .{
+ .Double = .{
+ .double = tok,
+ },
+ };
+ } else if (parser.eatToken(.Keyword_complex)) |tok| {
+ switch (type_spec.spec) {
+ .None => {
+ type_spec.spec = .{
+ .Double = .{
+ .complex = tok,
+ .double = null,
+ },
+ };
+ },
+ .Float => |*float| {
+ if (float.complex != null)
+ break :blk;
+ float.complex = tok;
+ },
+ .Double => |*double| {
+ if (double.complex != null)
+ break :blk;
+ double.complex = tok;
+ },
+ else => break :blk,
+ }
+ } else if (parser.eatToken(.Keyword_bool)) |tok| {
+ if (type_spec.spec != .None)
+ break :blk;
+ type_spec.spec = .{ .Bool = tok };
+ } else if (parser.eatToken(.Keyword_atomic)) |tok| {
+ // might be _Atomic qualifier
+ if (parser.eatToken(.LParen)) |_| {
+ if (type_spec.spec != .None)
+ break :blk;
+ const name = (try parser.typeName()) orelse return parser.err(.{
+ .ExpectedTypeName = .{ .token = parser.it.index },
+ });
+ type_spec.spec.Atomic = .{
+ .atomic = tok,
+ .typename = name,
+ .rparen = try parser.expectToken(.RParen),
+ };
+ } else {
+ parser.putBackToken(tok);
+ }
+ } else if (parser.eatToken(.Keyword_enum)) |tok| {
+ if (type_spec.spec != .None)
+ break :blk;
+ type_spec.spec.Enum = try parser.enumSpec(tok);
+ } else if (parser.eatToken(.Keyword_union) orelse parser.eatToken(.Keyword_struct)) |tok| {
+ if (type_spec.spec != .None)
+ break :blk;
+ type_spec.spec.Record = try parser.recordSpec(tok);
+ } else if (parser.eatToken(.Identifier)) |tok| {
+ const ty = parser.getSymbol(tok) orelse {
+ parser.putBackToken(tok);
+ return false;
+ };
+ switch (ty.id) {
+ .Enum => |e| blk: {
+ if (e.name) |some|
+ if (!parser.tree.tokenEql(some, tok))
+ break :blk;
+ return parser.err(.{
+ .MustUseKwToRefer = .{ .kw = e.tok, .name = tok },
+ });
+ },
+ .Record => |r| blk: {
+ if (r.name) |some|
+ if (!parser.tree.tokenEql(some, tok))
+ break :blk;
+ return parser.err(.{
+ .MustUseKwToRefer = .{
+ .kw = r.tok,
+ .name = tok,
+ },
+ });
+ },
+ .Typedef => {
+ type_spec.spec = .{
+ .Typedef = .{
+ .sym = tok,
+ .sym_type = ty,
+ },
+ };
+ return true;
+ },
+ else => {},
+ }
+ parser.putBackToken(tok);
+ return false;
+ }
+ return parser.typeQual(&type_spec.qual);
+ }
+ return parser.err(.{
+ .InvalidTypeSpecifier = .{
+ .token = parser.it.index,
+ .type_spec = type_spec,
+ },
+ });
+ }
+
+ /// TypeQual <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic
+ fn typeQual(parser: *Parser, qual: *Node.TypeQual) !bool {
+ blk: {
+ if (parser.eatToken(.Keyword_const)) |tok| {
+ if (qual.@"const" != null)
+ break :blk;
+ qual.@"const" = tok;
+ } else if (parser.eatToken(.Keyword_restrict)) |tok| {
+ if (qual.atomic != null)
+ break :blk;
+ qual.atomic = tok;
+ } else if (parser.eatToken(.Keyword_volatile)) |tok| {
+ if (qual.@"volatile" != null)
+ break :blk;
+ qual.@"volatile" = tok;
+ } else if (parser.eatToken(.Keyword_atomic)) |tok| {
+ if (qual.atomic != null)
+ break :blk;
+ qual.atomic = tok;
+ } else return false;
+ return true;
+ }
+ try parser.warn(.{
+ .DuplicateQualifier = .{ .token = parser.it.index },
+ });
+ return true;
+ }
+
+ /// FnSpec <- Keyword_inline / Keyword_noreturn
+ fn fnSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
+ blk: {
+ if (parser.eatToken(.Keyword_inline)) |tok| {
+ if (ds.fn_spec != .None)
+ break :blk;
+ ds.fn_spec = .{ .Inline = tok };
+ } else if (parser.eatToken(.Keyword_noreturn)) |tok| {
+ if (ds.fn_spec != .None)
+ break :blk;
+ ds.fn_spec = .{ .Noreturn = tok };
+ } else return false;
+ return true;
+ }
+ try parser.warn(.{
+ .DuplicateSpecifier = .{ .token = parser.it.index },
+ });
+ return true;
+ }
+
+ /// AlignSpec <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN
+ fn alignSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
+ if (parser.eatToken(.Keyword_alignas)) |tok| {
+ _ = try parser.expectToken(.LParen);
+ const node = (try parser.typeName()) orelse (try parser.constExpr()) orelse parser.err(.{
+ .ExpectedExpr = .{ .token = parser.it.index },
+ });
+ if (ds.align_spec != null) {
+ try parser.warn(.{
+ .DuplicateSpecifier = .{ .token = parser.it.index },
+ });
+ }
+ ds.align_spec = .{
+ .alignas = tok,
+ .expr = node,
+ .rparen = try parser.expectToken(.RParen),
+ };
+ return true;
+ }
+ return false;
+ }
+
+ /// EnumSpec <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)?
+ fn enumSpec(parser: *Parser, tok: TokenIndex) !*Node.EnumType {
+ const node = try parser.arena.create(Node.EnumType);
+ const name = parser.eatToken(.Identifier);
+ node.* = .{
+ .tok = tok,
+ .name = name,
+ .body = null,
+ };
+ const ty = try parser.arena.create(Type);
+ ty.* = .{
+ .id = .{
+ .Enum = node,
+ },
+ };
+ if (name) |some|
+ try parser.symbols.append(.{
+ .name = parser.tree.tokenSlice(some),
+ .ty = ty,
+ });
+ if (parser.eatToken(.LBrace)) |lbrace| {
+ var fields = Node.EnumType.FieldList.init(parser.arena);
+ try fields.push((try parser.enumField()) orelse return parser.err(.{
+ .ExpectedEnumField = .{ .token = parser.it.index },
+ }));
+ while (parser.eatToken(.Comma)) |_| {
+ try fields.push((try parser.enumField()) orelse break);
+ }
+ node.body = .{
+ .lbrace = lbrace,
+ .fields = fields,
+ .rbrace = try parser.expectToken(.RBrace),
+ };
+ }
+ return node;
+ }
+
+ /// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA?
+ fn enumField(parser: *Parser) !?*Node {
+ const name = parser.eatToken(.Identifier) orelse return null;
+ const node = try parser.arena.create(Node.EnumField);
+ node.* = .{
+ .name = name,
+ .value = null,
+ };
+ if (parser.eatToken(.Equal)) |eq| {
+ node.value = (try parser.constExpr()) orelse parser.err(.{
+ .ExpectedExpr = .{ .token = parser.it.index },
+ });
+ }
+ return &node.base;
+ }
+
+ /// RecordSpec <- (Keyword_struct / Keyword_union) IDENTIFIER? (LBRACE RecordField+ RBRACE)?
+ fn recordSpec(parser: *Parser, tok: TokenIndex) !*Node.RecordType {
+ const node = try parser.arena.create(Node.RecordType);
+ const name = parser.eatToken(.Identifier);
+ const is_struct = parser.tree.tokenSlice(tok)[0] == 's';
+ node.* = .{
+ .tok = tok,
+ .kind = if (is_struct) .Struct else .Union,
+ .name = name,
+ .body = null,
+ };
+ const ty = try parser.arena.create(Type);
+ ty.* = .{
+ .id = .{
+ .Record = node,
+ },
+ };
+ if (name) |some|
+ try parser.symbols.append(.{
+ .name = parser.tree.tokenSlice(some),
+ .ty = ty,
+ });
+ if (parser.eatToken(.LBrace)) |lbrace| {
+ try parser.pushScope(.Block);
+ defer parser.popScope();
+ var fields = Node.RecordType.FieldList.init(parser.arena);
+ while (true) {
+ if (parser.eatToken(.RBrace)) |rbrace| {
+ node.body = .{
+ .lbrace = lbrace,
+ .fields = fields,
+ .rbrace = rbrace,
+ };
+ break;
+ }
+ try fields.push(try parser.recordField());
+ }
+ }
+ return node;
+ }
+
+ /// RecordField
+ /// <- TypeSpec* (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON
+ /// \ StaticAssert
+ fn recordField(parser: *Parser) Error!*Node {
+ if (try parser.staticAssert()) |decl| return decl;
+ var got = false;
+ var type_spec = Node.TypeSpec{};
+ while (try parser.typeSpec(&type_spec)) got = true;
+ if (!got)
+ return parser.err(.{
+ .ExpectedType = .{ .token = parser.it.index },
+ });
+ const node = try parser.arena.create(Node.RecordField);
+ node.* = .{
+ .type_spec = type_spec,
+ .declarators = Node.RecordField.DeclaratorList.init(parser.arena),
+ .semicolon = undefined,
+ };
+ while (true) {
+ const rdr = try parser.recordDeclarator();
+ try parser.declareSymbol(type_spec, rdr.declarator);
+ try node.declarators.push(&rdr.base);
+ if (parser.eatToken(.Comma)) |_| {} else break;
+ }
+
+ node.semicolon = try parser.expectToken(.Semicolon);
+ return &node.base;
+ }
+
+ /// TypeName <- TypeSpec* AbstractDeclarator?
+ fn typeName(parser: *Parser) Error!?*Node {
+ @panic("TODO");
+ }
+
+ /// RecordDeclarator <- Declarator? (COLON ConstExpr)?
+ fn recordDeclarator(parser: *Parser) Error!*Node.RecordDeclarator {
+ @panic("TODO");
+ }
+
+ /// Pointer <- ASTERISK TypeQual* Pointer?
+ fn pointer(parser: *Parser) Error!?*Node.Pointer {
+ const asterisk = parser.eatToken(.Asterisk) orelse return null;
+ const node = try parser.arena.create(Node.Pointer);
+ node.* = .{
+ .asterisk = asterisk,
+ .qual = .{},
+ .pointer = null,
+ };
+ while (try parser.typeQual(&node.qual)) {}
+ node.pointer = try parser.pointer();
+ return node;
+ }
+
+ const Named = enum {
+ Must,
+ Allowed,
+ Forbidden,
+ };
+
+ /// Declarator <- Pointer? DeclaratorSuffix
+ /// DeclaratorPrefix
+ /// <- IDENTIFIER // if named != .Forbidden
+ /// / LPAREN Declarator RPAREN
+ /// / (none) // if named != .Must
+ /// DeclaratorSuffix
+ /// <- DeclaratorPrefix (LBRACKET ArrayDeclarator? RBRACKET)*
+ /// / DeclaratorPrefix LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
+ fn declarator(parser: *Parser, named: Named) Error!?*Node {
+ const ptr = try parser.pointer();
+ var node: *Node.Declarator = undefined;
+ var inner_fn = false;
+
+ // TODO sizof(int (int))
+ // prefix
+ if (parser.eatToken(.LParen)) |lparen| {
+ const inner = (try parser.declarator(named)) orelse return parser.err(.{
+ .ExpectedDeclarator = .{ .token = lparen + 1 },
+ });
+ inner_fn = declaratorIsFunction(inner);
+ node = try parser.arena.create(Node.Declarator);
+ node.* = .{
+ .pointer = ptr,
+ .prefix = .{
+ .Complex = .{
+ .lparen = lparen,
+ .inner = inner,
+ .rparen = try parser.expectToken(.RParen),
+ },
+ },
+ .suffix = .None,
+ };
+ } else if (named != .Forbidden) {
+ if (parser.eatToken(.Identifier)) |tok| {
+ node = try parser.arena.create(Node.Declarator);
+ node.* = .{
+ .pointer = ptr,
+ .prefix = .{ .Identifer = tok },
+ .suffix = .None,
+ };
+ } else if (named == .Must) {
+ return parser.err(.{
+ .ExpectedToken = .{ .token = parser.it.index, .expected_id = .Identifier },
+ });
+ } else {
+ if (ptr) |some|
+ return &some.base;
+ return null;
+ }
+ } else {
+ node = try parser.arena.create(Node.Declarator);
+ node.* = .{
+ .pointer = ptr,
+ .prefix = .None,
+ .suffix = .None,
+ };
+ }
+ // suffix
+ if (parser.eatToken(.LParen)) |lparen| {
+ if (inner_fn)
+ return parser.err(.{
+ .InvalidDeclarator = .{ .token = lparen },
+ });
+ node.suffix = .{
+ .Fn = .{
+ .lparen = lparen,
+ .params = Node.Declarator.Params.init(parser.arena),
+ .rparen = undefined,
+ },
+ };
+ try parser.paramDecl(node);
+ node.suffix.Fn.rparen = try parser.expectToken(.RParen);
+ } else if (parser.eatToken(.LBracket)) |tok| {
+ if (inner_fn)
+ return parser.err(.{
+ .InvalidDeclarator = .{ .token = tok },
+ });
+ node.suffix = .{ .Array = Node.Declarator.Arrays.init(parser.arena) };
+ var lbrace = tok;
+ while (true) {
+ try node.suffix.Array.push(try parser.arrayDeclarator(lbrace));
+ if (parser.eatToken(.LBracket)) |t| lbrace = t else break;
+ }
+ }
+ if (parser.eatToken(.LParen) orelse parser.eatToken(.LBracket)) |tok|
+ return parser.err(.{
+ .InvalidDeclarator = .{ .token = tok },
+ });
+ return &node.base;
+ }
+
+ /// ArrayDeclarator
+ /// <- ASTERISK
+ /// / Keyword_static TypeQual* AssignmentExpr
+ /// / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr)
+ /// / TypeQual+ AssignmentExpr?
+ /// / AssignmentExpr
+ fn arrayDeclarator(parser: *Parser, lbracket: TokenIndex) !*Node.Array {
+ const arr = try parser.arena.create(Node.Array);
+ arr.* = .{
+ .lbracket = lbracket,
+ .inner = .Inferred,
+ .rbracket = undefined,
+ };
+ if (parser.eatToken(.Asterisk)) |tok| {
+ arr.inner = .{ .Unspecified = tok };
+ } else {
+ // TODO
+ }
+ arr.rbracket = try parser.expectToken(.RBracket);
+ return arr;
+ }
+
+ /// Params <- ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?
+ /// ParamDecl <- DeclSpec (Declarator / AbstractDeclarator)
+ fn paramDecl(parser: *Parser, dr: *Node.Declarator) !void {
+ var old_style = false;
+ while (true) {
+ var ds = Node.DeclSpec{};
+ if (try parser.declSpec(&ds)) {
+ //TODO
+ // TODO try parser.declareSymbol(ds.type_spec, dr);
+ } else if (parser.eatToken(.Identifier)) |tok| {
+ old_style = true;
+ } else if (parser.eatToken(.Ellipsis)) |tok| {
+ // TODO
+ }
+ }
+ }
+
+ /// Expr <- AssignmentExpr (COMMA Expr)*
+ fn expr(parser: *Parser) Error!?*Expr {
+ @panic("TODO");
+ }
+
+ /// AssignmentExpr
+ /// <- ConditionalExpr // TODO recursive?
+ /// / UnaryExpr (EQUAL / ASTERISKEQUAL / SLASHEQUAL / PERCENTEQUAL / PLUSEQUAL / MINUSEQUA /
+ /// / ANGLEBRACKETANGLEBRACKETLEFTEQUAL / ANGLEBRACKETANGLEBRACKETRIGHTEQUAL /
+ /// / AMPERSANDEQUAL / CARETEQUAL / PIPEEQUAL) AssignmentExpr
+ fn assignmentExpr(parser: *Parser) !?*Expr {
+ @panic("TODO");
+ }
+
+ /// ConstExpr <- ConditionalExpr
+ fn constExpr(parser: *Parser) Error!?*Expr {
+ const start = parser.it.index;
+ const expression = try parser.conditionalExpr();
+ if (expression != null and expression.?.value == .None)
+ return parser.err(.{
+ .ConsExpr = start,
+ });
+ return expression;
+ }
+
+ /// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)?
+ fn conditionalExpr(parser: *Parser) Error!?*Expr {
+ @panic("TODO");
+ }
+
+ /// LogicalOrExpr <- LogicalAndExpr (PIPEPIPE LogicalOrExpr)*
+ fn logicalOrExpr(parser: *Parser) !*Node {
+ const lhs = (try parser.logicalAndExpr()) orelse return null;
+ }
+
+ /// LogicalAndExpr <- BinOrExpr (AMPERSANDAMPERSAND LogicalAndExpr)*
+ fn logicalAndExpr(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// BinOrExpr <- BinXorExpr (PIPE BinOrExpr)*
+ fn binOrExpr(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// BinXorExpr <- BinAndExpr (CARET BinXorExpr)*
+ fn binXorExpr(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// BinAndExpr <- EqualityExpr (AMPERSAND BinAndExpr)*
+ fn binAndExpr(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// EqualityExpr <- ComparisionExpr ((EQUALEQUAL / BANGEQUAL) EqualityExpr)*
+ fn equalityExpr(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// ComparisionExpr <- ShiftExpr (ANGLEBRACKETLEFT / ANGLEBRACKETLEFTEQUAL /ANGLEBRACKETRIGHT / ANGLEBRACKETRIGHTEQUAL) ComparisionExpr)*
+ fn comparisionExpr(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// ShiftExpr <- AdditiveExpr (ANGLEBRACKETANGLEBRACKETLEFT / ANGLEBRACKETANGLEBRACKETRIGHT) ShiftExpr)*
+ fn shiftExpr(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// AdditiveExpr <- MultiplicativeExpr (PLUS / MINUS) AdditiveExpr)*
+ fn additiveExpr(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// MultiplicativeExpr <- UnaryExpr (ASTERISK / SLASH / PERCENT) MultiplicativeExpr)*
+ fn multiplicativeExpr(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// UnaryExpr
+ /// <- LPAREN TypeName RPAREN UnaryExpr
+ /// / Keyword_sizeof LAPERN TypeName RPAREN
+ /// / Keyword_sizeof UnaryExpr
+ /// / Keyword_alignof LAPERN TypeName RPAREN
+ /// / (AMPERSAND / ASTERISK / PLUS / PLUSPLUS / MINUS / MINUSMINUS / TILDE / BANG) UnaryExpr
+ /// / PrimaryExpr PostFixExpr*
+ fn unaryExpr(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// PrimaryExpr
+ /// <- IDENTIFIER
+ /// / INTEGERLITERAL / FLOATLITERAL / STRINGLITERAL / CHARLITERAL
+ /// / LPAREN Expr RPAREN
+ /// / Keyword_generic LPAREN AssignmentExpr (COMMA Generic)+ RPAREN
+ fn primaryExpr(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// Generic
+ /// <- TypeName COLON AssignmentExpr
+ /// / Keyword_default COLON AssignmentExpr
+ fn generic(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// PostFixExpr
+ /// <- LPAREN TypeName RPAREN LBRACE Initializers RBRACE
+ /// / LBRACKET Expr RBRACKET
+ /// / LPAREN (AssignmentExpr (COMMA AssignmentExpr)*)? RPAREN
+ /// / (PERIOD / ARROW) IDENTIFIER
+ /// / (PLUSPLUS / MINUSMINUS)
+ fn postFixExpr(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// Initializers <- ((Designator+ EQUAL)? Initializer COMMA)* (Designator+ EQUAL)? Initializer COMMA?
+ fn initializers(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// Initializer
+ /// <- LBRACE Initializers RBRACE
+ /// / AssignmentExpr
+ fn initializer(parser: *Parser, dr: *Node.Declarator) Error!?*Node {
+ @panic("TODO");
+ }
+
+ /// Designator
+ /// <- LBRACKET ConstExpr RBRACKET
+ /// / PERIOD IDENTIFIER
+ fn designator(parser: *Parser) !*Node {
+ @panic("TODO");
+ }
+
+ /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE
+ fn compoundStmt(parser: *Parser) Error!?*Node {
+ const lbrace = parser.eatToken(.LBrace) orelse return null;
+ try parser.pushScope(.Block);
+ defer parser.popScope();
+ const body_node = try parser.arena.create(Node.CompoundStmt);
+ body_node.* = .{
+ .lbrace = lbrace,
+ .statements = Node.CompoundStmt.StmtList.init(parser.arena),
+ .rbrace = undefined,
+ };
+ while (true) {
+ if (parser.eatToken(.RBRACE)) |rbrace| {
+ body_node.rbrace = rbrace;
+ break;
+ }
+ try body_node.statements.push((try parser.declaration()) orelse (try parser.stmt()));
+ }
+ return &body_node.base;
+ }
+
+ /// Stmt
+ /// <- CompoundStmt
+ /// / Keyword_if LPAREN Expr RPAREN Stmt (Keyword_ELSE Stmt)?
+ /// / Keyword_switch LPAREN Expr RPAREN Stmt
+ /// / Keyword_while LPAREN Expr RPAREN Stmt
+ /// / Keyword_do statement Keyword_while LPAREN Expr RPAREN SEMICOLON
+ /// / Keyword_for LPAREN (Declaration / ExprStmt) ExprStmt Expr? RPAREN Stmt
+ /// / Keyword_default COLON Stmt
+ /// / Keyword_case ConstExpr COLON Stmt
+ /// / Keyword_goto IDENTIFIER SEMICOLON
+ /// / Keyword_continue SEMICOLON
+ /// / Keyword_break SEMICOLON
+ /// / Keyword_return Expr? SEMICOLON
+ /// / IDENTIFIER COLON Stmt
+ /// / ExprStmt
+ fn stmt(parser: *Parser) Error!*Node {
+ if (try parser.compoundStmt()) |node| return node;
+ if (parser.eatToken(.Keyword_if)) |tok| {
+ const node = try parser.arena.create(Node.IfStmt);
+ _ = try parser.expectToken(.LParen);
+ node.* = .{
+ .@"if" = tok,
+ .cond = (try parser.expr()) orelse return parser.err(.{
+ .ExpectedExpr = .{ .token = parser.it.index },
+ }),
+ .body = undefined,
+ .@"else" = null,
+ };
+ _ = try parser.expectToken(.RParen);
+ node.body = try parser.stmt();
+ if (parser.eatToken(.Keyword_else)) |else_tok| {
+ node.@"else" = .{
+ .tok = else_tok,
+ .body = try parser.stmt(),
+ };
+ }
+ return &node.base;
+ }
+ if (parser.eatToken(.Keyword_while)) |tok| {
+ try parser.pushScope(.Loop);
+ defer parser.popScope();
+ _ = try parser.expectToken(.LParen);
+ const cond = (try parser.expr()) orelse return parser.err(.{
+ .ExpectedExpr = .{ .token = parser.it.index },
+ });
+ const rparen = try parser.expectToken(.RParen);
+ const node = try parser.arena.create(Node.WhileStmt);
+ node.* = .{
+ .@"while" = tok,
+ .cond = cond,
+ .rparen = rparen,
+ .body = try parser.stmt(),
+ .semicolon = try parser.expectToken(.Semicolon),
+ };
+ return &node.base;
+ }
+ if (parser.eatToken(.Keyword_do)) |tok| {
+ try parser.pushScope(.Loop);
+ defer parser.popScope();
+ const body = try parser.stmt();
+ _ = try parser.expectToken(.LParen);
+ const cond = (try parser.expr()) orelse return parser.err(.{
+ .ExpectedExpr = .{ .token = parser.it.index },
+ });
+ _ = try parser.expectToken(.RParen);
+ const node = try parser.arena.create(Node.DoStmt);
+ node.* = .{
+ .do = tok,
+ .body = body,
+ .cond = cond,
+ .@"while" = @"while",
+ .semicolon = try parser.expectToken(.Semicolon),
+ };
+ return &node.base;
+ }
+ if (parser.eatToken(.Keyword_for)) |tok| {
+ try parser.pushScope(.Loop);
+ defer parser.popScope();
+ _ = try parser.expectToken(.LParen);
+ const init = if (try parser.declaration()) |decl| blk: {
+ // TODO disallow storage class other than auto and register
+ break :blk decl;
+ } else try parser.exprStmt();
+ const cond = try parser.expr();
+ const semicolon = try parser.expectToken(.Semicolon);
+ const incr = try parser.expr();
+ const rparen = try parser.expectToken(.RParen);
+ const node = try parser.arena.create(Node.ForStmt);
+ node.* = .{
+ .@"for" = tok,
+ .init = init,
+ .cond = cond,
+ .semicolon = semicolon,
+ .incr = incr,
+ .rparen = rparen,
+ .body = try parser.stmt(),
+ };
+ return &node.base;
+ }
+ if (parser.eatToken(.Keyword_switch)) |tok| {
+ try parser.pushScope(.Switch);
+ defer parser.popScope();
+ _ = try parser.expectToken(.LParen);
+ const switch_expr = try parser.exprStmt();
+ const rparen = try parser.expectToken(.RParen);
+ const node = try parser.arena.create(Node.SwitchStmt);
+ node.* = .{
+ .@"switch" = tok,
+ .expr = switch_expr,
+ .rparen = rparen,
+ .body = try parser.stmt(),
+ };
+ return &node.base;
+ }
+ if (parser.eatToken(.Keyword_default)) |tok| {
+ _ = try parser.expectToken(.Colon);
+ const node = try parser.arena.create(Node.LabeledStmt);
+ node.* = .{
+ .kind = .{ .Default = tok },
+ .stmt = try parser.stmt(),
+ };
+ return &node.base;
+ }
+ if (parser.eatToken(.Keyword_case)) |tok| {
+ _ = try parser.expectToken(.Colon);
+ const node = try parser.arena.create(Node.LabeledStmt);
+ node.* = .{
+ .kind = .{ .Case = tok },
+ .stmt = try parser.stmt(),
+ };
+ return &node.base;
+ }
+ if (parser.eatToken(.Keyword_goto)) |tok| {
+ const node = try parser.arena.create(Node.JumpStmt);
+ node.* = .{
+ .ltoken = tok,
+ .kind = .{ .Goto = tok },
+ .semicolon = try parser.expectToken(.Semicolon),
+ };
+ return &node.base;
+ }
+ if (parser.eatToken(.Keyword_continue)) |tok| {
+ const node = try parser.arena.create(Node.JumpStmt);
+ node.* = .{
+ .ltoken = tok,
+ .kind = .Continue,
+ .semicolon = try parser.expectToken(.Semicolon),
+ };
+ return &node.base;
+ }
+ if (parser.eatToken(.Keyword_break)) |tok| {
+ const node = try parser.arena.create(Node.JumpStmt);
+ node.* = .{
+ .ltoken = tok,
+ .kind = .Break,
+ .semicolon = try parser.expectToken(.Semicolon),
+ };
+ return &node.base;
+ }
+ if (parser.eatToken(.Keyword_return)) |tok| {
+ const node = try parser.arena.create(Node.JumpStmt);
+ node.* = .{
+ .ltoken = tok,
+ .kind = .{ .Return = try parser.expr() },
+ .semicolon = try parser.expectToken(.Semicolon),
+ };
+ return &node.base;
+ }
+ if (parser.eatToken(.Identifier)) |tok| {
+ if (parser.eatToken(.Colon)) |_| {
+ const node = try parser.arena.create(Node.LabeledStmt);
+ node.* = .{
+ .kind = .{ .Label = tok },
+ .stmt = try parser.stmt(),
+ };
+ return &node.base;
+ }
+ parser.putBackToken(tok);
+ }
+ return parser.exprStmt();
+ }
+
+ /// ExprStmt <- Expr? SEMICOLON
+ fn exprStmt(parser: *Parser) !*Node {
+ const node = try parser.arena.create(Node.ExprStmt);
+ node.* = .{
+ .expr = try parser.expr(),
+ .semicolon = try parser.expectToken(.Semicolon),
+ };
+ return &node.base;
+ }
+
+ fn eatToken(parser: *Parser, id: @TagType(Token.Id)) ?TokenIndex {
+ while (true) {
+ switch ((parser.it.next() orelse return null).id) {
+ .LineComment, .MultiLineComment, .Nl => continue,
+ else => |next_id| if (next_id == id) {
+ return parser.it.index;
+ } else {
+ _ = parser.it.prev();
+ return null;
+ },
+ }
+ }
+ }
+
+ fn expectToken(parser: *Parser, id: @TagType(Token.Id)) Error!TokenIndex {
+ while (true) {
+ switch ((parser.it.next() orelse return error.ParseError).id) {
+ .LineComment, .MultiLineComment, .Nl => continue,
+ else => |next_id| if (next_id != id) {
+ return parser.err(.{
+ .ExpectedToken = .{ .token = parser.it.index, .expected_id = id },
+ });
+ } else {
+ return parser.it.index;
+ },
+ }
+ }
+ }
+
+ fn putBackToken(parser: *Parser, putting_back: TokenIndex) void {
+ while (true) {
+ const prev_tok = parser.it.next() orelse return;
+ switch (prev_tok.id) {
+ .LineComment, .MultiLineComment, .Nl => continue,
+ else => {
+ assert(parser.it.list.at(putting_back) == prev_tok);
+ return;
+ },
+ }
+ }
+ }
+
+ fn err(parser: *Parser, msg: ast.Error) Error {
+ try parser.tree.msgs.push(.{
+ .kind = .Error,
+ .inner = msg,
+ });
+ return error.ParseError;
+ }
+
+ fn warn(parser: *Parser, msg: ast.Error) Error!void {
+ const is_warning = switch (parser.options.warn_as_err) {
+ .None => true,
+ .Some => |list| for (list) |item| (if (item == msg) break false) else true,
+ .All => false,
+ };
+ try parser.tree.msgs.push(.{
+ .kind = if (is_warning) .Warning else .Error,
+ .inner = msg,
+ });
+ if (!is_warning) return error.ParseError;
+ }
+
+ fn note(parser: *Parser, msg: ast.Error) Error!void {
+ try parser.tree.msgs.push(.{
+ .kind = .Note,
+ .inner = msg,
+ });
+ }
+};
+
diff --git a/lib/std/c/tokenizer.zig b/lib/std/c/tokenizer.zig
new file mode 100644
index 0000000000..a641529502
--- /dev/null
+++ b/lib/std/c/tokenizer.zig
@@ -0,0 +1,1583 @@
+const std = @import("std");
+const mem = std.mem;
+
+pub const Source = struct {
+ buffer: []const u8,
+ file_name: []const u8,
+ tokens: TokenList,
+
+ pub const TokenList = std.SegmentedList(Token, 64);
+};
+
+pub const Token = struct {
+ id: Id,
+ start: usize,
+ end: usize,
+ source: *Source,
+
+ pub const Id = union(enum) {
+ Invalid,
+ Eof,
+ Nl,
+ Identifier,
+
+ /// special case for #include <...>
+ MacroString,
+ StringLiteral: StrKind,
+ CharLiteral: StrKind,
+ IntegerLiteral: NumSuffix,
+ FloatLiteral: NumSuffix,
+ Bang,
+ BangEqual,
+ Pipe,
+ PipePipe,
+ PipeEqual,
+ Equal,
+ EqualEqual,
+ LParen,
+ RParen,
+ LBrace,
+ RBrace,
+ LBracket,
+ RBracket,
+ Period,
+ Ellipsis,
+ Caret,
+ CaretEqual,
+ Plus,
+ PlusPlus,
+ PlusEqual,
+ Minus,
+ MinusMinus,
+ MinusEqual,
+ Asterisk,
+ AsteriskEqual,
+ Percent,
+ PercentEqual,
+ Arrow,
+ Colon,
+ Semicolon,
+ Slash,
+ SlashEqual,
+ Comma,
+ Ampersand,
+ AmpersandAmpersand,
+ AmpersandEqual,
+ QuestionMark,
+ AngleBracketLeft,
+ AngleBracketLeftEqual,
+ AngleBracketAngleBracketLeft,
+ AngleBracketAngleBracketLeftEqual,
+ AngleBracketRight,
+ AngleBracketRightEqual,
+ AngleBracketAngleBracketRight,
+ AngleBracketAngleBracketRightEqual,
+ Tilde,
+ LineComment,
+ MultiLineComment,
+ Hash,
+ HashHash,
+
+ Keyword_auto,
+ Keyword_break,
+ Keyword_case,
+ Keyword_char,
+ Keyword_const,
+ Keyword_continue,
+ Keyword_default,
+ Keyword_do,
+ Keyword_double,
+ Keyword_else,
+ Keyword_enum,
+ Keyword_extern,
+ Keyword_float,
+ Keyword_for,
+ Keyword_goto,
+ Keyword_if,
+ Keyword_int,
+ Keyword_long,
+ Keyword_register,
+ Keyword_return,
+ Keyword_short,
+ Keyword_signed,
+ Keyword_sizeof,
+ Keyword_static,
+ Keyword_struct,
+ Keyword_switch,
+ Keyword_typedef,
+ Keyword_union,
+ Keyword_unsigned,
+ Keyword_void,
+ Keyword_volatile,
+ Keyword_while,
+
+ // ISO C99
+ Keyword_bool,
+ Keyword_complex,
+ Keyword_imaginary,
+ Keyword_inline,
+ Keyword_restrict,
+
+ // ISO C11
+ Keyword_alignas,
+ Keyword_alignof,
+ Keyword_atomic,
+ Keyword_generic,
+ Keyword_noreturn,
+ Keyword_static_assert,
+ Keyword_thread_local,
+
+ // Preprocessor directives
+ Keyword_include,
+ Keyword_define,
+ Keyword_ifdef,
+ Keyword_ifndef,
+ Keyword_error,
+ Keyword_pragma,
+
+ pub fn symbol(id: @TagType(Id)) []const u8 {
+ return switch (id) {
+ .Invalid => "Invalid",
+ .Eof => "Eof",
+ .Nl => "NewLine",
+ .Identifier => "Identifier",
+ .MacroString => "MacroString",
+ .StringLiteral => "StringLiteral",
+ .CharLiteral => "CharLiteral",
+ .IntegerLiteral => "IntegerLiteral",
+ .FloatLiteral => "FloatLiteral",
+ .LineComment => "LineComment",
+ .MultiLineComment => "MultiLineComment",
+
+ .Bang => "!",
+ .BangEqual => "!=",
+ .Pipe => "|",
+ .PipePipe => "||",
+ .PipeEqual => "|=",
+ .Equal => "=",
+ .EqualEqual => "==",
+ .LParen => "(",
+ .RParen => ")",
+ .LBrace => "{",
+ .RBrace => "}",
+ .LBracket => "[",
+ .RBracket => "]",
+ .Period => ".",
+ .Ellipsis => "...",
+ .Caret => "^",
+ .CaretEqual => "^=",
+ .Plus => "+",
+ .PlusPlus => "++",
+ .PlusEqual => "+=",
+ .Minus => "-",
+ .MinusMinus => "--",
+ .MinusEqual => "-=",
+ .Asterisk => "*",
+ .AsteriskEqual => "*=",
+ .Percent => "%",
+ .PercentEqual => "%=",
+ .Arrow => "->",
+ .Colon => ":",
+ .Semicolon => ";",
+ .Slash => "/",
+ .SlashEqual => "/=",
+ .Comma => ",",
+ .Ampersand => "&",
+ .AmpersandAmpersand => "&&",
+ .AmpersandEqual => "&=",
+ .QuestionMark => "?",
+ .AngleBracketLeft => "<",
+ .AngleBracketLeftEqual => "<=",
+ .AngleBracketAngleBracketLeft => "<<",
+ .AngleBracketAngleBracketLeftEqual => "<<=",
+ .AngleBracketRight => ">",
+ .AngleBracketRightEqual => ">=",
+ .AngleBracketAngleBracketRight => ">>",
+ .AngleBracketAngleBracketRightEqual => ">>=",
+ .Tilde => "~",
+ .Hash => "#",
+ .HashHash => "##",
+ .Keyword_auto => "auto",
+ .Keyword_break => "break",
+ .Keyword_case => "case",
+ .Keyword_char => "char",
+ .Keyword_const => "const",
+ .Keyword_continue => "continue",
+ .Keyword_default => "default",
+ .Keyword_do => "do",
+ .Keyword_double => "double",
+ .Keyword_else => "else",
+ .Keyword_enum => "enum",
+ .Keyword_extern => "extern",
+ .Keyword_float => "float",
+ .Keyword_for => "for",
+ .Keyword_goto => "goto",
+ .Keyword_if => "if",
+ .Keyword_int => "int",
+ .Keyword_long => "long",
+ .Keyword_register => "register",
+ .Keyword_return => "return",
+ .Keyword_short => "short",
+ .Keyword_signed => "signed",
+ .Keyword_sizeof => "sizeof",
+ .Keyword_static => "static",
+ .Keyword_struct => "struct",
+ .Keyword_switch => "switch",
+ .Keyword_typedef => "typedef",
+ .Keyword_union => "union",
+ .Keyword_unsigned => "unsigned",
+ .Keyword_void => "void",
+ .Keyword_volatile => "volatile",
+ .Keyword_while => "while",
+ .Keyword_bool => "_Bool",
+ .Keyword_complex => "_Complex",
+ .Keyword_imaginary => "_Imaginary",
+ .Keyword_inline => "inline",
+ .Keyword_restrict => "restrict",
+ .Keyword_alignas => "_Alignas",
+ .Keyword_alignof => "_Alignof",
+ .Keyword_atomic => "_Atomic",
+ .Keyword_generic => "_Generic",
+ .Keyword_noreturn => "_Noreturn",
+ .Keyword_static_assert => "_Static_assert",
+ .Keyword_thread_local => "_Thread_local",
+ .Keyword_include => "include",
+ .Keyword_define => "define",
+ .Keyword_ifdef => "ifdef",
+ .Keyword_ifndef => "ifndef",
+ .Keyword_error => "error",
+ .Keyword_pragma => "pragma",
+ };
+ }
+ };
+
+ pub fn eql(a: Token, b: Token) bool {
+ // do we really need this cast here
+ if (@as(@TagType(Id), a.id) != b.id) return false;
+ return mem.eql(u8, a.slice(), b.slice());
+ }
+
+ pub fn slice(tok: Token) []const u8 {
+ return tok.source.buffer[tok.start..tok.end];
+ }
+
+ pub const Keyword = struct {
+ bytes: []const u8,
+ id: Id,
+ hash: u32,
+
+ fn init(bytes: []const u8, id: Id) Keyword {
+ @setEvalBranchQuota(2000);
+ return .{
+ .bytes = bytes,
+ .id = id,
+ .hash = std.hash_map.hashString(bytes),
+ };
+ }
+ };
+
+ // TODO extensions
+ pub const keywords = [_]Keyword{
+ Keyword.init("auto", .Keyword_auto),
+ Keyword.init("break", .Keyword_break),
+ Keyword.init("case", .Keyword_case),
+ Keyword.init("char", .Keyword_char),
+ Keyword.init("const", .Keyword_const),
+ Keyword.init("continue", .Keyword_continue),
+ Keyword.init("default", .Keyword_default),
+ Keyword.init("do", .Keyword_do),
+ Keyword.init("double", .Keyword_double),
+ Keyword.init("else", .Keyword_else),
+ Keyword.init("enum", .Keyword_enum),
+ Keyword.init("extern", .Keyword_extern),
+ Keyword.init("float", .Keyword_float),
+ Keyword.init("for", .Keyword_for),
+ Keyword.init("goto", .Keyword_goto),
+ Keyword.init("if", .Keyword_if),
+ Keyword.init("int", .Keyword_int),
+ Keyword.init("long", .Keyword_long),
+ Keyword.init("register", .Keyword_register),
+ Keyword.init("return", .Keyword_return),
+ Keyword.init("short", .Keyword_short),
+ Keyword.init("signed", .Keyword_signed),
+ Keyword.init("sizeof", .Keyword_sizeof),
+ Keyword.init("static", .Keyword_static),
+ Keyword.init("struct", .Keyword_struct),
+ Keyword.init("switch", .Keyword_switch),
+ Keyword.init("typedef", .Keyword_typedef),
+ Keyword.init("union", .Keyword_union),
+ Keyword.init("unsigned", .Keyword_unsigned),
+ Keyword.init("void", .Keyword_void),
+ Keyword.init("volatile", .Keyword_volatile),
+ Keyword.init("while", .Keyword_while),
+
+ // ISO C99
+ Keyword.init("_Bool", .Keyword_bool),
+ Keyword.init("_Complex", .Keyword_complex),
+ Keyword.init("_Imaginary", .Keyword_imaginary),
+ Keyword.init("inline", .Keyword_inline),
+ Keyword.init("restrict", .Keyword_restrict),
+
+ // ISO C11
+ Keyword.init("_Alignas", .Keyword_alignas),
+ Keyword.init("_Alignof", .Keyword_alignof),
+ Keyword.init("_Atomic", .Keyword_atomic),
+ Keyword.init("_Generic", .Keyword_generic),
+ Keyword.init("_Noreturn", .Keyword_noreturn),
+ Keyword.init("_Static_assert", .Keyword_static_assert),
+ Keyword.init("_Thread_local", .Keyword_thread_local),
+
+ // Preprocessor directives
+ Keyword.init("include", .Keyword_include),
+ Keyword.init("define", .Keyword_define),
+ Keyword.init("ifdef", .Keyword_ifdef),
+ Keyword.init("ifndef", .Keyword_ifndef),
+ Keyword.init("error", .Keyword_error),
+ Keyword.init("pragma", .Keyword_pragma),
+ };
+
+ // TODO perfect hash at comptime
+ // TODO do this in the preprocessor
+ pub fn getKeyword(bytes: []const u8, pp_directive: bool) ?Id {
+ var hash = std.hash_map.hashString(bytes);
+ for (keywords) |kw| {
+ if (kw.hash == hash and mem.eql(u8, kw.bytes, bytes)) {
+ switch (kw.id) {
+ .Keyword_include,
+ .Keyword_define,
+ .Keyword_ifdef,
+ .Keyword_ifndef,
+ .Keyword_error,
+ .Keyword_pragma,
+ => if (!pp_directive) return null,
+ else => {},
+ }
+ return kw.id;
+ }
+ }
+ return null;
+ }
+
+ pub const NumSuffix = enum {
+ None,
+ F,
+ L,
+ U,
+ LU,
+ LL,
+ LLU,
+ };
+
+ pub const StrKind = enum {
+ None,
+ Wide,
+ Utf8,
+ Utf16,
+ Utf32,
+ };
+};
+
+pub const Tokenizer = struct {
+ source: *Source,
+ index: usize = 0,
+ prev_tok_id: @TagType(Token.Id) = .Invalid,
+ pp_directive: bool = false,
+
+ pub fn next(self: *Tokenizer) Token {
+ const start_index = self.index;
+ var result = Token{
+ .id = .Eof,
+ .start = self.index,
+ .end = undefined,
+ .source = self.source,
+ };
+ var state: enum {
+ Start,
+ Cr,
+ BackSlash,
+ BackSlashCr,
+ u,
+ u8,
+ U,
+ L,
+ StringLiteral,
+ CharLiteralStart,
+ CharLiteral,
+ EscapeSequence,
+ CrEscape,
+ OctalEscape,
+ HexEscape,
+ UnicodeEscape,
+ Identifier,
+ Equal,
+ Bang,
+ Pipe,
+ Percent,
+ Asterisk,
+ Plus,
+
+ /// special case for #include <...>
+ MacroString,
+ AngleBracketLeft,
+ AngleBracketAngleBracketLeft,
+ AngleBracketRight,
+ AngleBracketAngleBracketRight,
+ Caret,
+ Period,
+ Period2,
+ Minus,
+ Slash,
+ Ampersand,
+ Hash,
+ LineComment,
+ MultiLineComment,
+ MultiLineCommentAsterisk,
+ Zero,
+ IntegerLiteralOct,
+ IntegerLiteralBinary,
+ IntegerLiteralHex,
+ IntegerLiteral,
+ IntegerSuffix,
+ IntegerSuffixU,
+ IntegerSuffixL,
+ IntegerSuffixLL,
+ IntegerSuffixUL,
+ FloatFraction,
+ FloatFractionHex,
+ FloatExponent,
+ FloatExponentDigits,
+ FloatSuffix,
+ } = .Start;
+ var string = false;
+ var counter: u32 = 0;
+ while (self.index < self.source.buffer.len) : (self.index += 1) {
+ const c = self.source.buffer[self.index];
+ switch (state) {
+ .Start => switch (c) {
+ '\n' => {
+ self.pp_directive = false;
+ result.id = .Nl;
+ self.index += 1;
+ break;
+ },
+ '\r' => {
+ state = .Cr;
+ },
+ '"' => {
+ result.id = .{ .StringLiteral = .None };
+ state = .StringLiteral;
+ },
+ '\'' => {
+ result.id = .{ .CharLiteral = .None };
+ state = .CharLiteralStart;
+ },
+ 'u' => {
+ state = .u;
+ },
+ 'U' => {
+ state = .U;
+ },
+ 'L' => {
+ state = .L;
+ },
+ 'a'...'t', 'v'...'z', 'A'...'K', 'M'...'T', 'V'...'Z', '_' => {
+ state = .Identifier;
+ },
+ '=' => {
+ state = .Equal;
+ },
+ '!' => {
+ state = .Bang;
+ },
+ '|' => {
+ state = .Pipe;
+ },
+ '(' => {
+ result.id = .LParen;
+ self.index += 1;
+ break;
+ },
+ ')' => {
+ result.id = .RParen;
+ self.index += 1;
+ break;
+ },
+ '[' => {
+ result.id = .LBracket;
+ self.index += 1;
+ break;
+ },
+ ']' => {
+ result.id = .RBracket;
+ self.index += 1;
+ break;
+ },
+ ';' => {
+ result.id = .Semicolon;
+ self.index += 1;
+ break;
+ },
+ ',' => {
+ result.id = .Comma;
+ self.index += 1;
+ break;
+ },
+ '?' => {
+ result.id = .QuestionMark;
+ self.index += 1;
+ break;
+ },
+ ':' => {
+ result.id = .Colon;
+ self.index += 1;
+ break;
+ },
+ '%' => {
+ state = .Percent;
+ },
+ '*' => {
+ state = .Asterisk;
+ },
+ '+' => {
+ state = .Plus;
+ },
+ '<' => {
+ if (self.prev_tok_id == .Keyword_include)
+ state = .MacroString
+ else
+ state = .AngleBracketLeft;
+ },
+ '>' => {
+ state = .AngleBracketRight;
+ },
+ '^' => {
+ state = .Caret;
+ },
+ '{' => {
+ result.id = .LBrace;
+ self.index += 1;
+ break;
+ },
+ '}' => {
+ result.id = .RBrace;
+ self.index += 1;
+ break;
+ },
+ '~' => {
+ result.id = .Tilde;
+ self.index += 1;
+ break;
+ },
+ '.' => {
+ state = .Period;
+ },
+ '-' => {
+ state = .Minus;
+ },
+ '/' => {
+ state = .Slash;
+ },
+ '&' => {
+ state = .Ampersand;
+ },
+ '#' => {
+ state = .Hash;
+ },
+ '0' => {
+ state = .Zero;
+ },
+ '1'...'9' => {
+ state = .IntegerLiteral;
+ },
+ '\\' => {
+ state = .BackSlash;
+ },
+ '\t', '\x0B', '\x0C', ' ' => {
+ result.start = self.index + 1;
+ },
+ else => {
+ // TODO handle invalid bytes better
+ result.id = .Invalid;
+ self.index += 1;
+ break;
+ },
+ },
+ .Cr => switch (c) {
+ '\n' => {
+ self.pp_directive = false;
+ result.id = .Nl;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Invalid;
+ break;
+ },
+ },
+ .BackSlash => switch (c) {
+ '\n' => {
+ state = .Start;
+ },
+ '\r' => {
+ state = .BackSlashCr;
+ },
+ '\t', '\x0B', '\x0C', ' ' => {
+ // TODO warn
+ },
+ else => {
+ result.id = .Invalid;
+ break;
+ },
+ },
+ .BackSlashCr => switch (c) {
+ '\n' => {
+ state = .Start;
+ },
+ else => {
+ result.id = .Invalid;
+ break;
+ },
+ },
+ .u => switch (c) {
+ '8' => {
+ state = .u8;
+ },
+ '\'' => {
+ result.id = .{ .CharLiteral = .Utf16 };
+ state = .CharLiteralStart;
+ },
+ '\"' => {
+ result.id = .{ .StringLiteral = .Utf16 };
+ state = .StringLiteral;
+ },
+ else => {
+ state = .Identifier;
+ },
+ },
+ .u8 => switch (c) {
+ '\"' => {
+ result.id = .{ .StringLiteral = .Utf8 };
+ state = .StringLiteral;
+ },
+ else => {
+ state = .Identifier;
+ },
+ },
+ .U => switch (c) {
+ '\'' => {
+ result.id = .{ .CharLiteral = .Utf32 };
+ state = .CharLiteralStart;
+ },
+ '\"' => {
+ result.id = .{ .StringLiteral = .Utf32 };
+ state = .StringLiteral;
+ },
+ else => {
+ state = .Identifier;
+ },
+ },
+ .L => switch (c) {
+ '\'' => {
+ result.id = .{ .CharLiteral = .Wide };
+ state = .CharLiteralStart;
+ },
+ '\"' => {
+ result.id = .{ .StringLiteral = .Wide };
+ state = .StringLiteral;
+ },
+ else => {
+ state = .Identifier;
+ },
+ },
+ .StringLiteral => switch (c) {
+ '\\' => {
+ string = true;
+ state = .EscapeSequence;
+ },
+ '"' => {
+ self.index += 1;
+ break;
+ },
+ '\n', '\r' => {
+ result.id = .Invalid;
+ break;
+ },
+ else => {},
+ },
+ .CharLiteralStart => switch (c) {
+ '\\' => {
+ string = false;
+ state = .EscapeSequence;
+ },
+ '\'', '\n' => {
+ result.id = .Invalid;
+ break;
+ },
+ else => {
+ state = .CharLiteral;
+ },
+ },
+ .CharLiteral => switch (c) {
+ '\\' => {
+ string = false;
+ state = .EscapeSequence;
+ },
+ '\'' => {
+ self.index += 1;
+ break;
+ },
+ '\n' => {
+ result.id = .Invalid;
+ break;
+ },
+ else => {},
+ },
+ .EscapeSequence => switch (c) {
+ '\'', '"', '?', '\\', 'a', 'b', 'f', 'n', 'r', 't', 'v', '\n' => {
+ state = if (string) .StringLiteral else .CharLiteral;
+ },
+ '\r' => {
+ state = .CrEscape;
+ },
+ '0'...'7' => {
+ counter = 1;
+ state = .OctalEscape;
+ },
+ 'x' => {
+ state = .HexEscape;
+ },
+ 'u' => {
+ counter = 4;
+ state = .OctalEscape;
+ },
+ 'U' => {
+ counter = 8;
+ state = .OctalEscape;
+ },
+ else => {
+ result.id = .Invalid;
+ break;
+ },
+ },
+ .CrEscape => switch (c) {
+ '\n' => {
+ state = if (string) .StringLiteral else .CharLiteral;
+ },
+ else => {
+ result.id = .Invalid;
+ break;
+ },
+ },
+ .OctalEscape => switch (c) {
+ '0'...'7' => {
+ counter += 1;
+ if (counter == 3) {
+ state = if (string) .StringLiteral else .CharLiteral;
+ }
+ },
+ else => {
+ state = if (string) .StringLiteral else .CharLiteral;
+ },
+ },
+ .HexEscape => switch (c) {
+ '0'...'9', 'a'...'f', 'A'...'F' => {},
+ else => {
+ state = if (string) .StringLiteral else .CharLiteral;
+ },
+ },
+ .UnicodeEscape => switch (c) {
+ '0'...'9', 'a'...'f', 'A'...'F' => {
+ counter -= 1;
+ if (counter == 0) {
+ state = if (string) .StringLiteral else .CharLiteral;
+ }
+ },
+ else => {
+ if (counter != 0) {
+ result.id = .Invalid;
+ break;
+ }
+ state = if (string) .StringLiteral else .CharLiteral;
+ },
+ },
+ .Identifier => switch (c) {
+ 'a'...'z', 'A'...'Z', '_', '0'...'9' => {},
+ else => {
+ result.id = Token.getKeyword(self.source.buffer[result.start..self.index], self.prev_tok_id == .Hash and !self.pp_directive) orelse .Identifier;
+ if (self.prev_tok_id == .Hash)
+ self.pp_directive = true;
+ break;
+ },
+ },
+ .Equal => switch (c) {
+ '=' => {
+ result.id = .EqualEqual;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Equal;
+ break;
+ },
+ },
+ .Bang => switch (c) {
+ '=' => {
+ result.id = .BangEqual;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Bang;
+ break;
+ },
+ },
+ .Pipe => switch (c) {
+ '=' => {
+ result.id = .PipeEqual;
+ self.index += 1;
+ break;
+ },
+ '|' => {
+ result.id = .PipePipe;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Pipe;
+ break;
+ },
+ },
+ .Percent => switch (c) {
+ '=' => {
+ result.id = .PercentEqual;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Percent;
+ break;
+ },
+ },
+ .Asterisk => switch (c) {
+ '=' => {
+ result.id = .AsteriskEqual;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Asterisk;
+ break;
+ },
+ },
+ .Plus => switch (c) {
+ '=' => {
+ result.id = .PlusEqual;
+ self.index += 1;
+ break;
+ },
+ '+' => {
+ result.id = .PlusPlus;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Plus;
+ break;
+ },
+ },
+ .MacroString => switch (c) {
+ '>' => {
+ result.id = .MacroString;
+ self.index += 1;
+ break;
+ },
+ else => {},
+ },
+ .AngleBracketLeft => switch (c) {
+ '<' => {
+ state = .AngleBracketAngleBracketLeft;
+ },
+ '=' => {
+ result.id = .AngleBracketLeftEqual;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .AngleBracketLeft;
+ break;
+ },
+ },
+ .AngleBracketAngleBracketLeft => switch (c) {
+ '=' => {
+ result.id = .AngleBracketAngleBracketLeftEqual;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .AngleBracketAngleBracketLeft;
+ break;
+ },
+ },
+ .AngleBracketRight => switch (c) {
+ '>' => {
+ state = .AngleBracketAngleBracketRight;
+ },
+ '=' => {
+ result.id = .AngleBracketRightEqual;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .AngleBracketRight;
+ break;
+ },
+ },
+ .AngleBracketAngleBracketRight => switch (c) {
+ '=' => {
+ result.id = .AngleBracketAngleBracketRightEqual;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .AngleBracketAngleBracketRight;
+ break;
+ },
+ },
+ .Caret => switch (c) {
+ '=' => {
+ result.id = .CaretEqual;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Caret;
+ break;
+ },
+ },
+ .Period => switch (c) {
+ '.' => {
+ state = .Period2;
+ },
+ '0'...'9' => {
+ state = .FloatFraction;
+ },
+ else => {
+ result.id = .Period;
+ break;
+ },
+ },
+ .Period2 => switch (c) {
+ '.' => {
+ result.id = .Ellipsis;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Period;
+ self.index -= 1;
+ break;
+ },
+ },
+ .Minus => switch (c) {
+ '>' => {
+ result.id = .Arrow;
+ self.index += 1;
+ break;
+ },
+ '=' => {
+ result.id = .MinusEqual;
+ self.index += 1;
+ break;
+ },
+ '-' => {
+ result.id = .MinusMinus;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Minus;
+ break;
+ },
+ },
+ .Slash => switch (c) {
+ '/' => {
+ state = .LineComment;
+ },
+ '*' => {
+ state = .MultiLineComment;
+ },
+ '=' => {
+ result.id = .SlashEqual;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Slash;
+ break;
+ },
+ },
+ .Ampersand => switch (c) {
+ '&' => {
+ result.id = .AmpersandAmpersand;
+ self.index += 1;
+ break;
+ },
+ '=' => {
+ result.id = .AmpersandEqual;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Ampersand;
+ break;
+ },
+ },
+ .Hash => switch (c) {
+ '#' => {
+ result.id = .HashHash;
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .Hash;
+ break;
+ },
+ },
+ .LineComment => switch (c) {
+ '\n' => {
+ result.id = .LineComment;
+ self.index += 1;
+ break;
+ },
+ else => {},
+ },
+ .MultiLineComment => switch (c) {
+ '*' => {
+ state = .MultiLineCommentAsterisk;
+ },
+ else => {},
+ },
+ .MultiLineCommentAsterisk => switch (c) {
+ '/' => {
+ result.id = .MultiLineComment;
+ self.index += 1;
+ break;
+ },
+ else => {
+ state = .MultiLineComment;
+ },
+ },
+ .Zero => switch (c) {
+ '0'...'9' => {
+ state = .IntegerLiteralOct;
+ },
+ 'b', 'B' => {
+ state = .IntegerLiteralBinary;
+ },
+ 'x', 'X' => {
+ state = .IntegerLiteralHex;
+ },
+ else => {
+ state = .IntegerSuffix;
+ self.index -= 1;
+ },
+ },
+ .IntegerLiteralOct => switch (c) {
+ '0'...'7' => {},
+ else => {
+ state = .IntegerSuffix;
+ self.index -= 1;
+ },
+ },
+ .IntegerLiteralBinary => switch (c) {
+ '0', '1' => {},
+ else => {
+ state = .IntegerSuffix;
+ self.index -= 1;
+ },
+ },
+ .IntegerLiteralHex => switch (c) {
+ '0'...'9', 'a'...'f', 'A'...'F' => {},
+ '.' => {
+ state = .FloatFractionHex;
+ },
+ 'p', 'P' => {
+ state = .FloatExponent;
+ },
+ else => {
+ state = .IntegerSuffix;
+ self.index -= 1;
+ },
+ },
+ .IntegerLiteral => switch (c) {
+ '0'...'9' => {},
+ '.' => {
+ state = .FloatFraction;
+ },
+ 'e', 'E' => {
+ state = .FloatExponent;
+ },
+ else => {
+ state = .IntegerSuffix;
+ self.index -= 1;
+ },
+ },
+ .IntegerSuffix => switch (c) {
+ 'u', 'U' => {
+ state = .IntegerSuffixU;
+ },
+ 'l', 'L' => {
+ state = .IntegerSuffixL;
+ },
+ else => {
+ result.id = .{ .IntegerLiteral = .None };
+ break;
+ },
+ },
+ .IntegerSuffixU => switch (c) {
+ 'l', 'L' => {
+ state = .IntegerSuffixUL;
+ },
+ else => {
+ result.id = .{ .IntegerLiteral = .U };
+ break;
+ },
+ },
+ .IntegerSuffixL => switch (c) {
+ 'l', 'L' => {
+ state = .IntegerSuffixLL;
+ },
+ 'u', 'U' => {
+ result.id = .{ .IntegerLiteral = .LU };
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .{ .IntegerLiteral = .L };
+ break;
+ },
+ },
+ .IntegerSuffixLL => switch (c) {
+ 'u', 'U' => {
+ result.id = .{ .IntegerLiteral = .LLU };
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .{ .IntegerLiteral = .LL };
+ break;
+ },
+ },
+ .IntegerSuffixUL => switch (c) {
+ 'l', 'L' => {
+ result.id = .{ .IntegerLiteral = .LLU };
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .{ .IntegerLiteral = .LU };
+ break;
+ },
+ },
+ .FloatFraction => switch (c) {
+ '0'...'9' => {},
+ 'e', 'E' => {
+ state = .FloatExponent;
+ },
+ else => {
+ self.index -= 1;
+ state = .FloatSuffix;
+ },
+ },
+ .FloatFractionHex => switch (c) {
+ '0'...'9', 'a'...'f', 'A'...'F' => {},
+ 'p', 'P' => {
+ state = .FloatExponent;
+ },
+ else => {
+ result.id = .Invalid;
+ break;
+ },
+ },
+ .FloatExponent => switch (c) {
+ '+', '-' => {
+ state = .FloatExponentDigits;
+ },
+ else => {
+ self.index -= 1;
+ state = .FloatExponentDigits;
+ },
+ },
+ .FloatExponentDigits => switch (c) {
+ '0'...'9' => {
+ counter += 1;
+ },
+ else => {
+ if (counter == 0) {
+ result.id = .Invalid;
+ break;
+ }
+ state = .FloatSuffix;
+ },
+ },
+ .FloatSuffix => switch (c) {
+ 'l', 'L' => {
+ result.id = .{ .FloatLiteral = .L };
+ self.index += 1;
+ break;
+ },
+ 'f', 'F' => {
+ result.id = .{ .FloatLiteral = .F };
+ self.index += 1;
+ break;
+ },
+ else => {
+ result.id = .{ .FloatLiteral = .None };
+ break;
+ },
+ },
+ }
+ } else if (self.index == self.source.buffer.len) {
+ switch (state) {
+ .Start => {},
+ .u, .u8, .U, .L, .Identifier => {
+ result.id = Token.getKeyword(self.source.buffer[result.start..self.index], self.prev_tok_id == .Hash and !self.pp_directive) orelse .Identifier;
+ },
+
+ .Cr,
+ .BackSlash,
+ .BackSlashCr,
+ .Period2,
+ .StringLiteral,
+ .CharLiteralStart,
+ .CharLiteral,
+ .EscapeSequence,
+ .CrEscape,
+ .OctalEscape,
+ .HexEscape,
+ .UnicodeEscape,
+ .MultiLineComment,
+ .MultiLineCommentAsterisk,
+ .FloatFraction,
+ .FloatFractionHex,
+ .FloatExponent,
+ .FloatExponentDigits,
+ .MacroString,
+ => result.id = .Invalid,
+
+ .IntegerLiteralOct,
+ .IntegerLiteralBinary,
+ .IntegerLiteralHex,
+ .IntegerLiteral,
+ .IntegerSuffix,
+ .Zero,
+ => result.id = .{ .IntegerLiteral = .None },
+ .IntegerSuffixU => result.id = .{ .IntegerLiteral = .U },
+ .IntegerSuffixL => result.id = .{ .IntegerLiteral = .L },
+ .IntegerSuffixLL => result.id = .{ .IntegerLiteral = .LL },
+ .IntegerSuffixUL => result.id = .{ .IntegerLiteral = .LU },
+
+ .FloatSuffix => result.id = .{ .FloatLiteral = .None },
+ .Equal => result.id = .Equal,
+ .Bang => result.id = .Bang,
+ .Minus => result.id = .Minus,
+ .Slash => result.id = .Slash,
+ .Ampersand => result.id = .Ampersand,
+ .Hash => result.id = .Hash,
+ .Period => result.id = .Period,
+ .Pipe => result.id = .Pipe,
+ .AngleBracketAngleBracketRight => result.id = .AngleBracketAngleBracketRight,
+ .AngleBracketRight => result.id = .AngleBracketRight,
+ .AngleBracketAngleBracketLeft => result.id = .AngleBracketAngleBracketLeft,
+ .AngleBracketLeft => result.id = .AngleBracketLeft,
+ .Plus => result.id = .Plus,
+ .Percent => result.id = .Percent,
+ .Caret => result.id = .Caret,
+ .Asterisk => result.id = .Asterisk,
+ .LineComment => result.id = .LineComment,
+ }
+ }
+
+ self.prev_tok_id = result.id;
+ result.end = self.index;
+ return result;
+ }
+};
+
+test "operators" {
+ expectTokens(
+ \\ ! != | || |= = ==
+ \\ ( ) { } [ ] . .. ...
+ \\ ^ ^= + ++ += - -- -=
+ \\ * *= % %= -> : ; / /=
+ \\ , & && &= ? < <= <<
+ \\ <<= > >= >> >>= ~ # ##
+ \\
+ , &[_]Token.Id{
+ .Bang,
+ .BangEqual,
+ .Pipe,
+ .PipePipe,
+ .PipeEqual,
+ .Equal,
+ .EqualEqual,
+ .Nl,
+ .LParen,
+ .RParen,
+ .LBrace,
+ .RBrace,
+ .LBracket,
+ .RBracket,
+ .Period,
+ .Period,
+ .Period,
+ .Ellipsis,
+ .Nl,
+ .Caret,
+ .CaretEqual,
+ .Plus,
+ .PlusPlus,
+ .PlusEqual,
+ .Minus,
+ .MinusMinus,
+ .MinusEqual,
+ .Nl,
+ .Asterisk,
+ .AsteriskEqual,
+ .Percent,
+ .PercentEqual,
+ .Arrow,
+ .Colon,
+ .Semicolon,
+ .Slash,
+ .SlashEqual,
+ .Nl,
+ .Comma,
+ .Ampersand,
+ .AmpersandAmpersand,
+ .AmpersandEqual,
+ .QuestionMark,
+ .AngleBracketLeft,
+ .AngleBracketLeftEqual,
+ .AngleBracketAngleBracketLeft,
+ .Nl,
+ .AngleBracketAngleBracketLeftEqual,
+ .AngleBracketRight,
+ .AngleBracketRightEqual,
+ .AngleBracketAngleBracketRight,
+ .AngleBracketAngleBracketRightEqual,
+ .Tilde,
+ .Hash,
+ .HashHash,
+ .Nl,
+ });
+}
+
+test "keywords" {
+ expectTokens(
+ \\auto break case char const continue default do
+ \\double else enum extern float for goto if int
+ \\long register return short signed sizeof static
+ \\struct switch typedef union unsigned void volatile
+ \\while _Bool _Complex _Imaginary inline restrict _Alignas
+ \\_Alignof _Atomic _Generic _Noreturn _Static_assert _Thread_local
+ \\
+ , &[_]Token.Id{
+ .Keyword_auto,
+ .Keyword_break,
+ .Keyword_case,
+ .Keyword_char,
+ .Keyword_const,
+ .Keyword_continue,
+ .Keyword_default,
+ .Keyword_do,
+ .Nl,
+ .Keyword_double,
+ .Keyword_else,
+ .Keyword_enum,
+ .Keyword_extern,
+ .Keyword_float,
+ .Keyword_for,
+ .Keyword_goto,
+ .Keyword_if,
+ .Keyword_int,
+ .Nl,
+ .Keyword_long,
+ .Keyword_register,
+ .Keyword_return,
+ .Keyword_short,
+ .Keyword_signed,
+ .Keyword_sizeof,
+ .Keyword_static,
+ .Nl,
+ .Keyword_struct,
+ .Keyword_switch,
+ .Keyword_typedef,
+ .Keyword_union,
+ .Keyword_unsigned,
+ .Keyword_void,
+ .Keyword_volatile,
+ .Nl,
+ .Keyword_while,
+ .Keyword_bool,
+ .Keyword_complex,
+ .Keyword_imaginary,
+ .Keyword_inline,
+ .Keyword_restrict,
+ .Keyword_alignas,
+ .Nl,
+ .Keyword_alignof,
+ .Keyword_atomic,
+ .Keyword_generic,
+ .Keyword_noreturn,
+ .Keyword_static_assert,
+ .Keyword_thread_local,
+ .Nl,
+ });
+}
+
+test "preprocessor keywords" {
+ expectTokens(
+ \\#include <test>
+ \\#define #include <1
+ \\#ifdef
+ \\#ifndef
+ \\#error
+ \\#pragma
+ \\
+ , &[_]Token.Id{
+ .Hash,
+ .Keyword_include,
+ .MacroString,
+ .Nl,
+ .Hash,
+ .Keyword_define,
+ .Hash,
+ .Identifier,
+ .AngleBracketLeft,
+ .{ .IntegerLiteral = .None },
+ .Nl,
+ .Hash,
+ .Keyword_ifdef,
+ .Nl,
+ .Hash,
+ .Keyword_ifndef,
+ .Nl,
+ .Hash,
+ .Keyword_error,
+ .Nl,
+ .Hash,
+ .Keyword_pragma,
+ .Nl,
+ });
+}
+
+test "line continuation" {
+ expectTokens(
+ \\#define foo \
+ \\ bar
+ \\"foo\
+ \\ bar"
+ \\#define "foo"
+ \\ "bar"
+ \\#define "foo" \
+ \\ "bar"
+ , &[_]Token.Id{
+ .Hash,
+ .Keyword_define,
+ .Identifier,
+ .Identifier,
+ .Nl,
+ .{ .StringLiteral = .None },
+ .Nl,
+ .Hash,
+ .Keyword_define,
+ .{ .StringLiteral = .None },
+ .Nl,
+ .{ .StringLiteral = .None },
+ .Nl,
+ .Hash,
+ .Keyword_define,
+ .{ .StringLiteral = .None },
+ .{ .StringLiteral = .None },
+ });
+}
+
+test "string prefix" {
+ expectTokens(
+ \\"foo"
+ \\u"foo"
+ \\u8"foo"
+ \\U"foo"
+ \\L"foo"
+ \\'foo'
+ \\u'foo'
+ \\U'foo'
+ \\L'foo'
+ \\
+ , &[_]Token.Id{
+ .{ .StringLiteral = .None },
+ .Nl,
+ .{ .StringLiteral = .Utf16 },
+ .Nl,
+ .{ .StringLiteral = .Utf8 },
+ .Nl,
+ .{ .StringLiteral = .Utf32 },
+ .Nl,
+ .{ .StringLiteral = .Wide },
+ .Nl,
+ .{ .CharLiteral = .None },
+ .Nl,
+ .{ .CharLiteral = .Utf16 },
+ .Nl,
+ .{ .CharLiteral = .Utf32 },
+ .Nl,
+ .{ .CharLiteral = .Wide },
+ .Nl,
+ });
+}
+
+test "num suffixes" {
+ expectTokens(
+ \\ 1.0f 1.0L 1.0 .0 1.
+ \\ 0l 0lu 0ll 0llu 0
+ \\ 1u 1ul 1ull 1
+ \\
+ , &[_]Token.Id{
+ .{ .FloatLiteral = .F },
+ .{ .FloatLiteral = .L },
+ .{ .FloatLiteral = .None },
+ .{ .FloatLiteral = .None },
+ .{ .FloatLiteral = .None },
+ .Nl,
+ .{ .IntegerLiteral = .L },
+ .{ .IntegerLiteral = .LU },
+ .{ .IntegerLiteral = .LL },
+ .{ .IntegerLiteral = .LLU },
+ .{ .IntegerLiteral = .None },
+ .Nl,
+ .{ .IntegerLiteral = .U },
+ .{ .IntegerLiteral = .LU },
+ .{ .IntegerLiteral = .LLU },
+ .{ .IntegerLiteral = .None },
+ .Nl,
+ });
+}
+
+fn expectTokens(source: []const u8, expected_tokens: []const Token.Id) void {
+ var tokenizer = Tokenizer{
+ .source = &Source{
+ .buffer = source,
+ .file_name = undefined,
+ .tokens = undefined,
+ },
+ };
+ for (expected_tokens) |expected_token_id| {
+ const token = tokenizer.next();
+ if (!std.meta.eql(token.id, expected_token_id)) {
+ std.debug.panic("expected {}, found {}\n", .{ @tagName(expected_token_id), @tagName(token.id) });
+ }
+ }
+ const last_token = tokenizer.next();
+ std.testing.expect(last_token.id == .Eof);
+}
diff --git a/lib/std/debug.zig b/lib/std/debug.zig
index dfdaca6d3f..d035707a54 100644
--- a/lib/std/debug.zig
+++ b/lib/std/debug.zig
@@ -81,10 +81,20 @@ pub fn getSelfDebugInfo() !*DebugInfo {
}
}
-fn wantTtyColor() bool {
+pub fn detectTTYConfig() TTY.Config {
var bytes: [128]u8 = undefined;
const allocator = &std.heap.FixedBufferAllocator.init(bytes[0..]).allocator;
- return if (process.getEnvVarOwned(allocator, "ZIG_DEBUG_COLOR")) |_| true else |_| stderr_file.isTty();
+ if (process.getEnvVarOwned(allocator, "ZIG_DEBUG_COLOR")) |_| {
+ return .escape_codes;
+ } else |_| {
+ if (stderr_file.supportsAnsiEscapeCodes()) {
+ return .escape_codes;
+ } else if (builtin.os == .windows and stderr_file.isTty()) {
+ return .windows_api;
+ } else {
+ return .no_color;
+ }
+ }
}
/// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned.
@@ -99,7 +109,7 @@ pub fn dumpCurrentStackTrace(start_addr: ?usize) void {
stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return;
return;
};
- writeCurrentStackTrace(stderr, debug_info, wantTtyColor(), start_addr) catch |err| {
+ writeCurrentStackTrace(stderr, debug_info, detectTTYConfig(), start_addr) catch |err| {
stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return;
return;
};
@@ -118,16 +128,16 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {
stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return;
return;
};
- const tty_color = wantTtyColor();
- printSourceAtAddress(debug_info, stderr, ip, tty_color) catch return;
+ const tty_config = detectTTYConfig();
+ printSourceAtAddress(debug_info, stderr, ip, tty_config) catch return;
const first_return_address = @intToPtr(*const usize, bp + @sizeOf(usize)).*;
- printSourceAtAddress(debug_info, stderr, first_return_address - 1, tty_color) catch return;
+ printSourceAtAddress(debug_info, stderr, first_return_address - 1, tty_config) catch return;
var it = StackIterator{
.first_addr = null,
.fp = bp,
};
while (it.next()) |return_address| {
- printSourceAtAddress(debug_info, stderr, return_address - 1, tty_color) catch return;
+ printSourceAtAddress(debug_info, stderr, return_address - 1, tty_config) catch return;
}
}
@@ -191,7 +201,7 @@ pub fn dumpStackTrace(stack_trace: builtin.StackTrace) void {
stderr.print("Unable to dump stack trace: Unable to open debug info: {}\n", .{@errorName(err)}) catch return;
return;
};
- writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, wantTtyColor()) catch |err| {
+ writeStackTrace(stack_trace, stderr, getDebugInfoAllocator(), debug_info, detectTTYConfig()) catch |err| {
stderr.print("Unable to dump stack trace: {}\n", .{@errorName(err)}) catch return;
return;
};
@@ -264,7 +274,7 @@ pub fn writeStackTrace(
out_stream: var,
allocator: *mem.Allocator,
debug_info: *DebugInfo,
- tty_color: bool,
+ tty_config: TTY.Config,
) !void {
if (builtin.strip_debug_info) return error.MissingDebugInfo;
var frame_index: usize = 0;
@@ -275,7 +285,7 @@ pub fn writeStackTrace(
frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len;
}) {
const return_address = stack_trace.instruction_addresses[frame_index];
- try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_color);
+ try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config);
}
}
@@ -319,20 +329,25 @@ pub const StackIterator = struct {
}
};
-pub fn writeCurrentStackTrace(out_stream: var, debug_info: *DebugInfo, tty_color: bool, start_addr: ?usize) !void {
+pub fn writeCurrentStackTrace(
+ out_stream: var,
+ debug_info: *DebugInfo,
+ tty_config: TTY.Config,
+ start_addr: ?usize,
+) !void {
if (builtin.os == .windows) {
- return writeCurrentStackTraceWindows(out_stream, debug_info, tty_color, start_addr);
+ return writeCurrentStackTraceWindows(out_stream, debug_info, tty_config, start_addr);
}
var it = StackIterator.init(start_addr);
while (it.next()) |return_address| {
- try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_color);
+ try printSourceAtAddress(debug_info, out_stream, return_address - 1, tty_config);
}
}
pub fn writeCurrentStackTraceWindows(
out_stream: var,
debug_info: *DebugInfo,
- tty_color: bool,
+ tty_config: TTY.Config,
start_addr: ?usize,
) !void {
var addr_buf: [1024]usize = undefined;
@@ -345,23 +360,28 @@ pub fn writeCurrentStackTraceWindows(
return;
} else 0;
for (addrs[start_i..]) |addr| {
- try printSourceAtAddress(debug_info, out_stream, addr, tty_color);
+ try printSourceAtAddress(debug_info, out_stream, addr - 1, tty_config);
}
}
/// TODO once https://github.com/ziglang/zig/issues/3157 is fully implemented,
/// make this `noasync fn` and remove the individual noasync calls.
-pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
+pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
if (builtin.os == .windows) {
- return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_color);
+ return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_config);
}
if (comptime std.Target.current.isDarwin()) {
- return noasync printSourceAtAddressMacOs(debug_info, out_stream, address, tty_color);
+ return noasync printSourceAtAddressMacOs(debug_info, out_stream, address, tty_config);
}
- return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_color);
+ return noasync printSourceAtAddressPosix(debug_info, out_stream, address, tty_config);
}
-fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_address: usize, tty_color: bool) !void {
+fn printSourceAtAddressWindows(
+ di: *DebugInfo,
+ out_stream: var,
+ relocated_address: usize,
+ tty_config: TTY.Config,
+) !void {
const allocator = getDebugInfoAllocator();
const base_address = process.getBaseAddress();
const relative_address = relocated_address - base_address;
@@ -379,16 +399,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
}
} else {
// we have no information to add to the address
- if (tty_color) {
- try out_stream.print("???:?:?: ", .{});
- setTtyColor(TtyColor.Dim);
- try out_stream.print("0x{x} in ??? (???)", .{relocated_address});
- setTtyColor(TtyColor.Reset);
- try out_stream.print("\n\n\n", .{});
- } else {
- try out_stream.print("???:?:?: 0x{x} in ??? (???)\n\n\n", .{relocated_address});
- }
- return;
+ return printLineInfo(out_stream, null, relocated_address, "???", "???", tty_config, printLineFromFileAnyOs);
};
const mod = &di.modules[mod_index];
@@ -401,7 +412,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
if (prefix.RecordLen < 2)
return error.InvalidDebugInfo;
switch (prefix.RecordKind) {
- pdb.SymbolKind.S_LPROC32 => {
+ .S_LPROC32, .S_GPROC32 => {
const proc_sym = @ptrCast(*pdb.ProcSym, &mod.symbols[symbol_i + @sizeOf(pdb.RecordPrefix)]);
const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;
const vaddr_end = vaddr_start + proc_sym.CodeSize;
@@ -510,137 +521,86 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
}
};
- if (tty_color) {
- setTtyColor(TtyColor.White);
- if (opt_line_info) |li| {
- try out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column });
- } else {
- try out_stream.print("???:?:?", .{});
- }
- setTtyColor(TtyColor.Reset);
- try out_stream.print(": ", .{});
- setTtyColor(TtyColor.Dim);
- try out_stream.print("0x{x} in {} ({})", .{ relocated_address, symbol_name, obj_basename });
- setTtyColor(TtyColor.Reset);
-
- if (opt_line_info) |line_info| {
- try out_stream.print("\n", .{});
- if (printLineFromFileAnyOs(out_stream, line_info)) {
- if (line_info.column == 0) {
- try out_stream.write("\n");
- } else {
- {
- var col_i: usize = 1;
- while (col_i < line_info.column) : (col_i += 1) {
- try out_stream.writeByte(' ');
- }
- }
- setTtyColor(TtyColor.Green);
- try out_stream.write("^");
- setTtyColor(TtyColor.Reset);
- try out_stream.write("\n");
- }
- } else |err| switch (err) {
- error.EndOfFile => {},
- error.FileNotFound => {
- setTtyColor(TtyColor.Dim);
- try out_stream.write("file not found\n\n");
- setTtyColor(TtyColor.White);
- },
- else => return err,
- }
- } else {
- try out_stream.print("\n\n\n", .{});
- }
- } else {
- if (opt_line_info) |li| {
- try out_stream.print("{}:{}:{}: 0x{x} in {} ({})\n\n\n", .{
- li.file_name,
- li.line,
- li.column,
- relocated_address,
- symbol_name,
- obj_basename,
- });
- } else {
- try out_stream.print("???:?:?: 0x{x} in {} ({})\n\n\n", .{
- relocated_address,
- symbol_name,
- obj_basename,
- });
- }
- }
+ try printLineInfo(
+ out_stream,
+ opt_line_info,
+ relocated_address,
+ symbol_name,
+ obj_basename,
+ tty_config,
+ printLineFromFileAnyOs,
+ );
}
-const TtyColor = enum {
- Red,
- Green,
- Cyan,
- White,
- Dim,
- Bold,
- Reset,
-};
+pub const TTY = struct {
+ pub const Color = enum {
+ Red,
+ Green,
+ Cyan,
+ White,
+ Dim,
+ Bold,
+ Reset,
+ };
-/// TODO this is a special case hack right now. clean it up and maybe make it part of std.fmt
-fn setTtyColor(tty_color: TtyColor) void {
- if (stderr_file.supportsAnsiEscapeCodes()) {
- switch (tty_color) {
- TtyColor.Red => {
- stderr_file.write(RED) catch return;
- },
- TtyColor.Green => {
- stderr_file.write(GREEN) catch return;
- },
- TtyColor.Cyan => {
- stderr_file.write(CYAN) catch return;
- },
- TtyColor.White, TtyColor.Bold => {
- stderr_file.write(WHITE) catch return;
- },
- TtyColor.Dim => {
- stderr_file.write(DIM) catch return;
- },
- TtyColor.Reset => {
- stderr_file.write(RESET) catch return;
- },
- }
- } else {
- const S = struct {
- var attrs: windows.WORD = undefined;
- var init_attrs = false;
- };
- if (!S.init_attrs) {
- S.init_attrs = true;
- var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
- // TODO handle error
- _ = windows.kernel32.GetConsoleScreenBufferInfo(stderr_file.handle, &info);
- S.attrs = info.wAttributes;
- }
+ pub const Config = enum {
+ no_color,
+ escape_codes,
+ // TODO give this a payload of file handle
+ windows_api,
+
+ fn setColor(conf: Config, out_stream: var, color: Color) void {
+ switch (conf) {
+ .no_color => return,
+ .escape_codes => switch (color) {
+ .Red => out_stream.write(RED) catch return,
+ .Green => out_stream.write(GREEN) catch return,
+ .Cyan => out_stream.write(CYAN) catch return,
+ .White, .Bold => out_stream.write(WHITE) catch return,
+ .Dim => out_stream.write(DIM) catch return,
+ .Reset => out_stream.write(RESET) catch return,
+ },
+ .windows_api => if (builtin.os == .windows) {
+ const S = struct {
+ var attrs: windows.WORD = undefined;
+ var init_attrs = false;
+ };
+ if (!S.init_attrs) {
+ S.init_attrs = true;
+ var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
+ // TODO handle error
+ _ = windows.kernel32.GetConsoleScreenBufferInfo(stderr_file.handle, &info);
+ S.attrs = info.wAttributes;
+ }
- // TODO handle errors
- switch (tty_color) {
- TtyColor.Red => {
- _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY) catch {};
- },
- TtyColor.Green => {
- _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY) catch {};
- },
- TtyColor.Cyan => {
- _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {};
- },
- TtyColor.White, TtyColor.Bold => {
- _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {};
- },
- TtyColor.Dim => {
- _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_INTENSITY) catch {};
- },
- TtyColor.Reset => {
- _ = windows.SetConsoleTextAttribute(stderr_file.handle, S.attrs) catch {};
- },
+ // TODO handle errors
+ switch (color) {
+ .Red => {
+ _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_INTENSITY) catch {};
+ },
+ .Green => {
+ _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_INTENSITY) catch {};
+ },
+ .Cyan => {
+ _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {};
+ },
+ .White, .Bold => {
+ _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_RED | windows.FOREGROUND_GREEN | windows.FOREGROUND_BLUE | windows.FOREGROUND_INTENSITY) catch {};
+ },
+ .Dim => {
+ _ = windows.SetConsoleTextAttribute(stderr_file.handle, windows.FOREGROUND_INTENSITY) catch {};
+ },
+ .Reset => {
+ _ = windows.SetConsoleTextAttribute(stderr_file.handle, S.attrs) catch {};
+ },
+ }
+ } else {
+ unreachable;
+ },
+ }
}
- }
-}
+ };
+};
fn populateModule(di: *DebugInfo, mod: *Module) !void {
if (mod.populated)
@@ -706,17 +666,12 @@ fn machoSearchSymbols(symbols: []const MachoSymbol, address: usize) ?*const Mach
return null;
}
-fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
+fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
const base_addr = process.getBaseAddress();
const adjusted_addr = 0x100000000 + (address - base_addr);
const symbol = machoSearchSymbols(di.symbols, adjusted_addr) orelse {
- if (tty_color) {
- try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", .{address});
- } else {
- try out_stream.print("???:?:?: 0x{x} in ??? (???)\n\n\n", .{address});
- }
- return;
+ return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFileAnyOs);
};
const symbol_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + symbol.nlist.n_strx));
@@ -724,78 +679,70 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx));
break :blk fs.path.basename(ofile_path);
} else "???";
- if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
- defer line_info.deinit();
- try printLineInfo(
- out_stream,
- line_info,
- address,
- symbol_name,
- compile_unit_name,
- tty_color,
- printLineFromFileAnyOs,
- );
- } else |err| switch (err) {
- error.MissingDebugInfo, error.InvalidDebugInfo => {
- if (tty_color) {
- try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in {} ({})" ++ RESET ++ "\n\n\n", .{
- address, symbol_name, compile_unit_name,
- });
- } else {
- try out_stream.print("???:?:?: 0x{x} in {} ({})\n\n\n", .{ address, symbol_name, compile_unit_name });
- }
- },
+
+ const line_info = getLineNumberInfoMacOs(di, symbol.*, adjusted_addr) catch |err| switch (err) {
+ error.MissingDebugInfo, error.InvalidDebugInfo => null,
else => return err,
- }
+ };
+ defer if (line_info) |li| li.deinit();
+
+ try printLineInfo(
+ out_stream,
+ line_info,
+ address,
+ symbol_name,
+ compile_unit_name,
+ tty_config,
+ printLineFromFileAnyOs,
+ );
}
-pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_color: bool) !void {
- return debug_info.printSourceAtAddress(out_stream, address, tty_color, printLineFromFileAnyOs);
+pub fn printSourceAtAddressPosix(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
+ return debug_info.printSourceAtAddress(out_stream, address, tty_config, printLineFromFileAnyOs);
}
fn printLineInfo(
out_stream: var,
- line_info: LineInfo,
+ line_info: ?LineInfo,
address: usize,
symbol_name: []const u8,
compile_unit_name: []const u8,
- tty_color: bool,
+ tty_config: TTY.Config,
comptime printLineFromFile: var,
) !void {
- if (tty_color) {
- try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ DIM ++ "0x{x} in {} ({})" ++ RESET ++ "\n", .{
- line_info.file_name,
- line_info.line,
- line_info.column,
- address,
- symbol_name,
- compile_unit_name,
- });
- if (printLineFromFile(out_stream, line_info)) {
- if (line_info.column == 0) {
- try out_stream.write("\n");
- } else {
- {
- var col_i: usize = 1;
- while (col_i < line_info.column) : (col_i += 1) {
- try out_stream.writeByte(' ');
- }
- }
- try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n");
+ tty_config.setColor(out_stream, .White);
+
+ if (line_info) |*li| {
+ try out_stream.print("{}:{}:{}", .{ li.file_name, li.line, li.column });
+ } else {
+ try out_stream.print("???:?:?", .{});
+ }
+
+ tty_config.setColor(out_stream, .Reset);
+ try out_stream.write(": ");
+ tty_config.setColor(out_stream, .Dim);
+ try out_stream.print("0x{x} in {} ({})", .{ address, symbol_name, compile_unit_name });
+ tty_config.setColor(out_stream, .Reset);
+ try out_stream.write("\n");
+
+ // Show the matching source code line if possible
+ if (line_info) |li| {
+ if (noasync printLineFromFile(out_stream, li)) {
+ if (li.column > 0) {
+ // The caret already takes one char
+ const space_needed = @intCast(usize, li.column - 1);
+
+ try out_stream.writeByteNTimes(' ', space_needed);
+ tty_config.setColor(out_stream, .Green);
+ try out_stream.write("^");
+ tty_config.setColor(out_stream, .Reset);
}
+ try out_stream.write("\n");
} else |err| switch (err) {
error.EndOfFile, error.FileNotFound => {},
+ error.BadPathName => {},
else => return err,
}
- } else {
- try out_stream.print("{}:{}:{}: 0x{x} in {} ({})\n", .{
- line_info.file_name,
- line_info.line,
- line_info.column,
- address,
- symbol_name,
- compile_unit_name,
- });
}
}
@@ -1016,59 +963,61 @@ pub fn openDwarfDebugInfo(di: *DwarfInfo, allocator: *mem.Allocator) !void {
pub fn openElfDebugInfo(
allocator: *mem.Allocator,
- elf_seekable_stream: *DwarfSeekableStream,
- elf_in_stream: *DwarfInStream,
+ data: []u8,
) !DwarfInfo {
- var efile = try elf.Elf.openStream(allocator, elf_seekable_stream, elf_in_stream);
- errdefer efile.close();
+ var seekable_stream = io.SliceSeekableInStream.init(data);
+ var efile = try elf.Elf.openStream(
+ allocator,
+ @ptrCast(*DwarfSeekableStream, &seekable_stream.seekable_stream),
+ @ptrCast(*DwarfInStream, &seekable_stream.stream),
+ );
+ defer efile.close();
+
+ const debug_info = (try efile.findSection(".debug_info")) orelse
+ return error.MissingDebugInfo;
+ const debug_abbrev = (try efile.findSection(".debug_abbrev")) orelse
+ return error.MissingDebugInfo;
+ const debug_str = (try efile.findSection(".debug_str")) orelse
+ return error.MissingDebugInfo;
+ const debug_line = (try efile.findSection(".debug_line")) orelse
+ return error.MissingDebugInfo;
+ const opt_debug_ranges = try efile.findSection(".debug_ranges");
var di = DwarfInfo{
- .dwarf_seekable_stream = elf_seekable_stream,
- .dwarf_in_stream = elf_in_stream,
.endian = efile.endian,
- .debug_info = (try findDwarfSectionFromElf(&efile, ".debug_info")) orelse return error.MissingDebugInfo,
- .debug_abbrev = (try findDwarfSectionFromElf(&efile, ".debug_abbrev")) orelse return error.MissingDebugInfo,
- .debug_str = (try findDwarfSectionFromElf(&efile, ".debug_str")) orelse return error.MissingDebugInfo,
- .debug_line = (try findDwarfSectionFromElf(&efile, ".debug_line")) orelse return error.MissingDebugInfo,
- .debug_ranges = (try findDwarfSectionFromElf(&efile, ".debug_ranges")),
- .abbrev_table_list = undefined,
- .compile_unit_list = undefined,
- .func_list = undefined,
+ .debug_info = (data[@intCast(usize, debug_info.offset)..@intCast(usize, debug_info.offset + debug_info.size)]),
+ .debug_abbrev = (data[@intCast(usize, debug_abbrev.offset)..@intCast(usize, debug_abbrev.offset + debug_abbrev.size)]),
+ .debug_str = (data[@intCast(usize, debug_str.offset)..@intCast(usize, debug_str.offset + debug_str.size)]),
+ .debug_line = (data[@intCast(usize, debug_line.offset)..@intCast(usize, debug_line.offset + debug_line.size)]),
+ .debug_ranges = if (opt_debug_ranges) |debug_ranges|
+ data[@intCast(usize, debug_ranges.offset)..@intCast(usize, debug_ranges.offset + debug_ranges.size)]
+ else
+ null,
};
+
+ efile.close();
+
try openDwarfDebugInfo(&di, allocator);
return di;
}
fn openSelfDebugInfoPosix(allocator: *mem.Allocator) !DwarfInfo {
- const S = struct {
- var self_exe_file: File = undefined;
- var self_exe_mmap_seekable: io.SliceSeekableInStream = undefined;
- };
-
- S.self_exe_file = try fs.openSelfExe();
- errdefer S.self_exe_file.close();
+ var exe_file = try fs.openSelfExe();
+ errdefer exe_file.close();
- const self_exe_len = math.cast(usize, try S.self_exe_file.getEndPos()) catch return error.DebugInfoTooLarge;
- const self_exe_mmap_len = mem.alignForward(self_exe_len, mem.page_size);
- const self_exe_mmap = try os.mmap(
+ const exe_len = math.cast(usize, try exe_file.getEndPos()) catch
+ return error.DebugInfoTooLarge;
+ const exe_mmap = try os.mmap(
null,
- self_exe_mmap_len,
+ exe_len,
os.PROT_READ,
os.MAP_SHARED,
- S.self_exe_file.handle,
+ exe_file.handle,
0,
);
- errdefer os.munmap(self_exe_mmap);
+ errdefer os.munmap(exe_mmap);
- S.self_exe_mmap_seekable = io.SliceSeekableInStream.init(self_exe_mmap);
-
- return openElfDebugInfo(
- allocator,
- // TODO https://github.com/ziglang/zig/issues/764
- @ptrCast(*DwarfSeekableStream, &S.self_exe_mmap_seekable.seekable_stream),
- // TODO https://github.com/ziglang/zig/issues/764
- @ptrCast(*DwarfInStream, &S.self_exe_mmap_seekable.stream),
- );
+ return openElfDebugInfo(allocator, exe_mmap);
}
fn openSelfDebugInfoMacOs(allocator: *mem.Allocator) !DebugInfo {
@@ -1195,83 +1144,56 @@ const MachoSymbol = struct {
}
};
-const MachOFile = struct {
- bytes: []align(@alignOf(macho.mach_header_64)) const u8,
- sect_debug_info: ?*const macho.section_64,
- sect_debug_line: ?*const macho.section_64,
-};
-
pub const DwarfSeekableStream = io.SeekableStream(anyerror, anyerror);
pub const DwarfInStream = io.InStream(anyerror);
pub const DwarfInfo = struct {
- dwarf_seekable_stream: *DwarfSeekableStream,
- dwarf_in_stream: *DwarfInStream,
endian: builtin.Endian,
- debug_info: Section,
- debug_abbrev: Section,
- debug_str: Section,
- debug_line: Section,
- debug_ranges: ?Section,
- abbrev_table_list: ArrayList(AbbrevTableHeader),
- compile_unit_list: ArrayList(CompileUnit),
- func_list: ArrayList(Func),
-
- pub const Section = struct {
- offset: u64,
- size: u64,
- };
+ // No memory is owned by the DwarfInfo
+ debug_info: []u8,
+ debug_abbrev: []u8,
+ debug_str: []u8,
+ debug_line: []u8,
+ debug_ranges: ?[]u8,
+ // Filled later by the initializer
+ abbrev_table_list: ArrayList(AbbrevTableHeader) = undefined,
+ compile_unit_list: ArrayList(CompileUnit) = undefined,
+ func_list: ArrayList(Func) = undefined,
pub fn allocator(self: DwarfInfo) *mem.Allocator {
return self.abbrev_table_list.allocator;
}
- pub fn readString(self: *DwarfInfo) ![]u8 {
- return readStringRaw(self.allocator(), self.dwarf_in_stream);
- }
-
/// This function works in freestanding mode.
/// fn printLineFromFile(out_stream: var, line_info: LineInfo) !void
pub fn printSourceAtAddress(
self: *DwarfInfo,
out_stream: var,
address: usize,
- tty_color: bool,
+ tty_config: TTY.Config,
comptime printLineFromFile: var,
) !void {
const compile_unit = self.findCompileUnit(address) catch {
- if (tty_color) {
- try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? (???)" ++ RESET ++ "\n\n\n", .{address});
- } else {
- try out_stream.print("???:?:?: 0x{x} in ??? (???)\n\n\n", .{address});
- }
- return;
+ return printLineInfo(out_stream, null, address, "???", "???", tty_config, printLineFromFile);
};
+
const compile_unit_name = try compile_unit.die.getAttrString(self, DW.AT_name);
- if (self.getLineNumberInfo(compile_unit.*, address)) |line_info| {
- defer line_info.deinit();
- const symbol_name = self.getSymbolName(address) orelse "???";
- try printLineInfo(
- out_stream,
- line_info,
- address,
- symbol_name,
- compile_unit_name,
- tty_color,
- printLineFromFile,
- );
- } else |err| switch (err) {
- error.MissingDebugInfo, error.InvalidDebugInfo => {
- if (tty_color) {
- try out_stream.print("???:?:?: " ++ DIM ++ "0x{x} in ??? ({})" ++ RESET ++ "\n\n\n", .{
- address, compile_unit_name,
- });
- } else {
- try out_stream.print("???:?:?: 0x{x} in ??? ({})\n\n\n", .{ address, compile_unit_name });
- }
- },
+ const symbol_name = self.getSymbolName(address) orelse "???";
+ const line_info = self.getLineNumberInfo(compile_unit.*, address) catch |err| switch (err) {
+ error.MissingDebugInfo, error.InvalidDebugInfo => null,
else => return err,
- }
+ };
+ defer if (line_info) |li| li.deinit();
+
+ try printLineInfo(
+ out_stream,
+ line_info,
+ address,
+ symbol_name,
+ compile_unit_name,
+ tty_config,
+ printLineFromFile,
+ );
}
fn getSymbolName(di: *DwarfInfo, address: u64) ?[]const u8 {
@@ -1287,35 +1209,38 @@ pub const DwarfInfo = struct {
}
fn scanAllFunctions(di: *DwarfInfo) !void {
- const debug_info_end = di.debug_info.offset + di.debug_info.size;
- var this_unit_offset = di.debug_info.offset;
+ var s = io.SliceSeekableInStream.init(di.debug_info);
+ var this_unit_offset: u64 = 0;
- while (this_unit_offset < debug_info_end) {
- try di.dwarf_seekable_stream.seekTo(this_unit_offset);
+ while (true) {
+ s.seekable_stream.seekTo(this_unit_offset) catch |err| switch (err) {
+ error.EndOfStream => return,
+ else => return err,
+ };
var is_64: bool = undefined;
- const unit_length = try readInitialLength(@TypeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
+ const unit_length = try readInitialLength(@TypeOf(s.stream.readFn).ReturnType.ErrorSet, &s.stream, &is_64);
if (unit_length == 0) return;
const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
- const version = try di.dwarf_in_stream.readInt(u16, di.endian);
+ const version = try s.stream.readInt(u16, di.endian);
if (version < 2 or version > 5) return error.InvalidDebugInfo;
- const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
+ const debug_abbrev_offset = if (is_64) try s.stream.readInt(u64, di.endian) else try s.stream.readInt(u32, di.endian);
- const address_size = try di.dwarf_in_stream.readByte();
+ const address_size = try s.stream.readByte();
if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
- const compile_unit_pos = try di.dwarf_seekable_stream.getPos();
+ const compile_unit_pos = try s.seekable_stream.getPos();
const abbrev_table = try di.getAbbrevTable(debug_abbrev_offset);
- try di.dwarf_seekable_stream.seekTo(compile_unit_pos);
+ try s.seekable_stream.seekTo(compile_unit_pos);
const next_unit_pos = this_unit_offset + next_offset;
- while ((try di.dwarf_seekable_stream.getPos()) < next_unit_pos) {
- const die_obj = (try di.parseDie(abbrev_table, is_64)) orelse continue;
- const after_die_offset = try di.dwarf_seekable_stream.getPos();
+ while ((try s.seekable_stream.getPos()) < next_unit_pos) {
+ const die_obj = (try di.parseDie(&s.stream, abbrev_table, is_64)) orelse continue;
+ const after_die_offset = try s.seekable_stream.getPos();
switch (die_obj.tag_id) {
DW.TAG_subprogram, DW.TAG_inlined_subroutine, DW.TAG_subroutine, DW.TAG_entry_point => {
@@ -1331,14 +1256,14 @@ pub const DwarfInfo = struct {
// Follow the DIE it points to and repeat
const ref_offset = try this_die_obj.getAttrRef(DW.AT_abstract_origin);
if (ref_offset > next_offset) return error.InvalidDebugInfo;
- try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset);
- this_die_obj = (try di.parseDie(abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
+ try s.seekable_stream.seekTo(this_unit_offset + ref_offset);
+ this_die_obj = (try di.parseDie(&s.stream, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
} else if (this_die_obj.getAttr(DW.AT_specification)) |ref| {
// Follow the DIE it points to and repeat
const ref_offset = try this_die_obj.getAttrRef(DW.AT_specification);
if (ref_offset > next_offset) return error.InvalidDebugInfo;
- try di.dwarf_seekable_stream.seekTo(this_unit_offset + ref_offset);
- this_die_obj = (try di.parseDie(abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
+ try s.seekable_stream.seekTo(this_unit_offset + ref_offset);
+ this_die_obj = (try di.parseDie(&s.stream, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
} else {
break :x null;
}
@@ -1376,12 +1301,10 @@ pub const DwarfInfo = struct {
.pc_range = pc_range,
});
},
- else => {
- continue;
- },
+ else => {},
}
- try di.dwarf_seekable_stream.seekTo(after_die_offset);
+ try s.seekable_stream.seekTo(after_die_offset);
}
this_unit_offset += next_offset;
@@ -1389,32 +1312,35 @@ pub const DwarfInfo = struct {
}
fn scanAllCompileUnits(di: *DwarfInfo) !void {
- const debug_info_end = di.debug_info.offset + di.debug_info.size;
- var this_unit_offset = di.debug_info.offset;
+ var s = io.SliceSeekableInStream.init(di.debug_info);
+ var this_unit_offset: u64 = 0;
- while (this_unit_offset < debug_info_end) {
- try di.dwarf_seekable_stream.seekTo(this_unit_offset);
+ while (true) {
+ s.seekable_stream.seekTo(this_unit_offset) catch |err| switch (err) {
+ error.EndOfStream => return,
+ else => return err,
+ };
var is_64: bool = undefined;
- const unit_length = try readInitialLength(@TypeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
+ const unit_length = try readInitialLength(@TypeOf(s.stream.readFn).ReturnType.ErrorSet, &s.stream, &is_64);
if (unit_length == 0) return;
const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
- const version = try di.dwarf_in_stream.readInt(u16, di.endian);
+ const version = try s.stream.readInt(u16, di.endian);
if (version < 2 or version > 5) return error.InvalidDebugInfo;
- const debug_abbrev_offset = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
+ const debug_abbrev_offset = if (is_64) try s.stream.readInt(u64, di.endian) else try s.stream.readInt(u32, di.endian);
- const address_size = try di.dwarf_in_stream.readByte();
+ const address_size = try s.stream.readByte();
if (address_size != @sizeOf(usize)) return error.InvalidDebugInfo;
- const compile_unit_pos = try di.dwarf_seekable_stream.getPos();
+ const compile_unit_pos = try s.seekable_stream.getPos();
const abbrev_table = try di.getAbbrevTable(debug_abbrev_offset);
- try di.dwarf_seekable_stream.seekTo(compile_unit_pos);
+ try s.seekable_stream.seekTo(compile_unit_pos);
const compile_unit_die = try di.allocator().create(Die);
- compile_unit_die.* = (try di.parseDie(abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
+ compile_unit_die.* = (try di.parseDie(&s.stream, abbrev_table, is_64)) orelse return error.InvalidDebugInfo;
if (compile_unit_die.tag_id != DW.TAG_compile_unit) return error.InvalidDebugInfo;
@@ -1458,28 +1384,38 @@ pub const DwarfInfo = struct {
if (compile_unit.pc_range) |range| {
if (target_address >= range.start and target_address < range.end) return compile_unit;
}
- if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {
- var base_address: usize = 0;
- if (di.debug_ranges) |debug_ranges| {
- try di.dwarf_seekable_stream.seekTo(debug_ranges.offset + ranges_offset);
+ if (di.debug_ranges) |debug_ranges| {
+ if (compile_unit.die.getAttrSecOffset(DW.AT_ranges)) |ranges_offset| {
+ var s = io.SliceSeekableInStream.init(debug_ranges);
+
+ // All the addresses in the list are relative to the value
+ // specified by DW_AT_low_pc or to some other value encoded
+ // in the list itself
+ var base_address = try compile_unit.die.getAttrAddr(DW.AT_low_pc);
+
+ try s.seekable_stream.seekTo(ranges_offset);
+
while (true) {
- const begin_addr = try di.dwarf_in_stream.readIntLittle(usize);
- const end_addr = try di.dwarf_in_stream.readIntLittle(usize);
+ const begin_addr = try s.stream.readIntLittle(usize);
+ const end_addr = try s.stream.readIntLittle(usize);
if (begin_addr == 0 and end_addr == 0) {
break;
}
+ // This entry selects a new value for the base address
if (begin_addr == maxInt(usize)) {
- base_address = begin_addr;
+ base_address = end_addr;
continue;
}
- if (target_address >= begin_addr and target_address < end_addr) {
+ if (target_address >= base_address + begin_addr and target_address < base_address + end_addr) {
return compile_unit;
}
}
+
+ return error.InvalidDebugInfo;
+ } else |err| {
+ if (err != error.MissingDebugInfo) return err;
+ continue;
}
- } else |err| {
- if (err != error.MissingDebugInfo) return err;
- continue;
}
}
return error.MissingDebugInfo;
@@ -1493,30 +1429,33 @@ pub const DwarfInfo = struct {
return &header.table;
}
}
- try di.dwarf_seekable_stream.seekTo(di.debug_abbrev.offset + abbrev_offset);
try di.abbrev_table_list.append(AbbrevTableHeader{
.offset = abbrev_offset,
- .table = try di.parseAbbrevTable(),
+ .table = try di.parseAbbrevTable(abbrev_offset),
});
return &di.abbrev_table_list.items[di.abbrev_table_list.len - 1].table;
}
- fn parseAbbrevTable(di: *DwarfInfo) !AbbrevTable {
+ fn parseAbbrevTable(di: *DwarfInfo, offset: u64) !AbbrevTable {
+ var s = io.SliceSeekableInStream.init(di.debug_abbrev);
+
+ try s.seekable_stream.seekTo(offset);
var result = AbbrevTable.init(di.allocator());
+ errdefer result.deinit();
while (true) {
- const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
+ const abbrev_code = try leb.readULEB128(u64, &s.stream);
if (abbrev_code == 0) return result;
try result.append(AbbrevTableEntry{
.abbrev_code = abbrev_code,
- .tag_id = try leb.readULEB128(u64, di.dwarf_in_stream),
- .has_children = (try di.dwarf_in_stream.readByte()) == DW.CHILDREN_yes,
+ .tag_id = try leb.readULEB128(u64, &s.stream),
+ .has_children = (try s.stream.readByte()) == DW.CHILDREN_yes,
.attrs = ArrayList(AbbrevAttr).init(di.allocator()),
});
const attrs = &result.items[result.len - 1].attrs;
while (true) {
- const attr_id = try leb.readULEB128(u64, di.dwarf_in_stream);
- const form_id = try leb.readULEB128(u64, di.dwarf_in_stream);
+ const attr_id = try leb.readULEB128(u64, &s.stream);
+ const form_id = try leb.readULEB128(u64, &s.stream);
if (attr_id == 0 and form_id == 0) break;
try attrs.append(AbbrevAttr{
.attr_id = attr_id,
@@ -1526,8 +1465,8 @@ pub const DwarfInfo = struct {
}
}
- fn parseDie(di: *DwarfInfo, abbrev_table: *const AbbrevTable, is_64: bool) !?Die {
- const abbrev_code = try leb.readULEB128(u64, di.dwarf_in_stream);
+ fn parseDie(di: *DwarfInfo, in_stream: var, abbrev_table: *const AbbrevTable, is_64: bool) !?Die {
+ const abbrev_code = try leb.readULEB128(u64, in_stream);
if (abbrev_code == 0) return null;
const table_entry = getAbbrevTableEntry(abbrev_table, abbrev_code) orelse return error.InvalidDebugInfo;
@@ -1540,63 +1479,63 @@ pub const DwarfInfo = struct {
for (table_entry.attrs.toSliceConst()) |attr, i| {
result.attrs.items[i] = Die.Attr{
.id = attr.attr_id,
- .value = try parseFormValue(di.allocator(), di.dwarf_in_stream, attr.form_id, is_64),
+ .value = try parseFormValue(di.allocator(), in_stream, attr.form_id, is_64),
};
}
return result;
}
fn getLineNumberInfo(di: *DwarfInfo, compile_unit: CompileUnit, target_address: usize) !LineInfo {
+ var s = io.SliceSeekableInStream.init(di.debug_line);
+
const compile_unit_cwd = try compile_unit.die.getAttrString(di, DW.AT_comp_dir);
const line_info_offset = try compile_unit.die.getAttrSecOffset(DW.AT_stmt_list);
- assert(line_info_offset < di.debug_line.size);
-
- try di.dwarf_seekable_stream.seekTo(di.debug_line.offset + line_info_offset);
+ try s.seekable_stream.seekTo(line_info_offset);
var is_64: bool = undefined;
- const unit_length = try readInitialLength(@TypeOf(di.dwarf_in_stream.readFn).ReturnType.ErrorSet, di.dwarf_in_stream, &is_64);
+ const unit_length = try readInitialLength(@TypeOf(s.stream.readFn).ReturnType.ErrorSet, &s.stream, &is_64);
if (unit_length == 0) {
return error.MissingDebugInfo;
}
const next_offset = unit_length + (if (is_64) @as(usize, 12) else @as(usize, 4));
- const version = try di.dwarf_in_stream.readInt(u16, di.endian);
+ const version = try s.stream.readInt(u16, di.endian);
// TODO support 3 and 5
if (version != 2 and version != 4) return error.InvalidDebugInfo;
- const prologue_length = if (is_64) try di.dwarf_in_stream.readInt(u64, di.endian) else try di.dwarf_in_stream.readInt(u32, di.endian);
- const prog_start_offset = (try di.dwarf_seekable_stream.getPos()) + prologue_length;
+ const prologue_length = if (is_64) try s.stream.readInt(u64, di.endian) else try s.stream.readInt(u32, di.endian);
+ const prog_start_offset = (try s.seekable_stream.getPos()) + prologue_length;
- const minimum_instruction_length = try di.dwarf_in_stream.readByte();
+ const minimum_instruction_length = try s.stream.readByte();
if (minimum_instruction_length == 0) return error.InvalidDebugInfo;
if (version >= 4) {
// maximum_operations_per_instruction
- _ = try di.dwarf_in_stream.readByte();
+ _ = try s.stream.readByte();
}
- const default_is_stmt = (try di.dwarf_in_stream.readByte()) != 0;
- const line_base = try di.dwarf_in_stream.readByteSigned();
+ const default_is_stmt = (try s.stream.readByte()) != 0;
+ const line_base = try s.stream.readByteSigned();
- const line_range = try di.dwarf_in_stream.readByte();
+ const line_range = try s.stream.readByte();
if (line_range == 0) return error.InvalidDebugInfo;
- const opcode_base = try di.dwarf_in_stream.readByte();
+ const opcode_base = try s.stream.readByte();
const standard_opcode_lengths = try di.allocator().alloc(u8, opcode_base - 1);
{
var i: usize = 0;
while (i < opcode_base - 1) : (i += 1) {
- standard_opcode_lengths[i] = try di.dwarf_in_stream.readByte();
+ standard_opcode_lengths[i] = try s.stream.readByte();
}
}
var include_directories = ArrayList([]u8).init(di.allocator());
try include_directories.append(compile_unit_cwd);
while (true) {
- const dir = try di.readString();
+ const dir = try readStringRaw(di.allocator(), &s.stream);
if (dir.len == 0) break;
try include_directories.append(dir);
}
@@ -1605,11 +1544,11 @@ pub const DwarfInfo = struct {
var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address);
while (true) {
- const file_name = try di.readString();
+ const file_name = try readStringRaw(di.allocator(), &s.stream);
if (file_name.len == 0) break;
- const dir_index = try leb.readULEB128(usize, di.dwarf_in_stream);
- const mtime = try leb.readULEB128(usize, di.dwarf_in_stream);
- const len_bytes = try leb.readULEB128(usize, di.dwarf_in_stream);
+ const dir_index = try leb.readULEB128(usize, &s.stream);
+ const mtime = try leb.readULEB128(usize, &s.stream);
+ const len_bytes = try leb.readULEB128(usize, &s.stream);
try file_entries.append(FileEntry{
.file_name = file_name,
.dir_index = dir_index,
@@ -1618,30 +1557,32 @@ pub const DwarfInfo = struct {
});
}
- try di.dwarf_seekable_stream.seekTo(prog_start_offset);
+ try s.seekable_stream.seekTo(prog_start_offset);
- while (true) {
- const opcode = try di.dwarf_in_stream.readByte();
+ const next_unit_pos = line_info_offset + next_offset;
+
+ while ((try s.seekable_stream.getPos()) < next_unit_pos) {
+ const opcode = try s.stream.readByte();
if (opcode == DW.LNS_extended_op) {
- const op_size = try leb.readULEB128(u64, di.dwarf_in_stream);
+ const op_size = try leb.readULEB128(u64, &s.stream);
if (op_size < 1) return error.InvalidDebugInfo;
- var sub_op = try di.dwarf_in_stream.readByte();
+ var sub_op = try s.stream.readByte();
switch (sub_op) {
DW.LNE_end_sequence => {
prog.end_sequence = true;
if (try prog.checkLineMatch()) |info| return info;
- return error.MissingDebugInfo;
+ prog.reset();
},
DW.LNE_set_address => {
- const addr = try di.dwarf_in_stream.readInt(usize, di.endian);
+ const addr = try s.stream.readInt(usize, di.endian);
prog.address = addr;
},
DW.LNE_define_file => {
- const file_name = try di.readString();
- const dir_index = try leb.readULEB128(usize, di.dwarf_in_stream);
- const mtime = try leb.readULEB128(usize, di.dwarf_in_stream);
- const len_bytes = try leb.readULEB128(usize, di.dwarf_in_stream);
+ const file_name = try readStringRaw(di.allocator(), &s.stream);
+ const dir_index = try leb.readULEB128(usize, &s.stream);
+ const mtime = try leb.readULEB128(usize, &s.stream);
+ const len_bytes = try leb.readULEB128(usize, &s.stream);
try file_entries.append(FileEntry{
.file_name = file_name,
.dir_index = dir_index,
@@ -1651,7 +1592,7 @@ pub const DwarfInfo = struct {
},
else => {
const fwd_amt = math.cast(isize, op_size - 1) catch return error.InvalidDebugInfo;
- try di.dwarf_seekable_stream.seekBy(fwd_amt);
+ try s.seekable_stream.seekBy(fwd_amt);
},
}
} else if (opcode >= opcode_base) {
@@ -1670,19 +1611,19 @@ pub const DwarfInfo = struct {
prog.basic_block = false;
},
DW.LNS_advance_pc => {
- const arg = try leb.readULEB128(usize, di.dwarf_in_stream);
+ const arg = try leb.readULEB128(usize, &s.stream);
prog.address += arg * minimum_instruction_length;
},
DW.LNS_advance_line => {
- const arg = try leb.readILEB128(i64, di.dwarf_in_stream);
+ const arg = try leb.readILEB128(i64, &s.stream);
prog.line += arg;
},
DW.LNS_set_file => {
- const arg = try leb.readULEB128(usize, di.dwarf_in_stream);
+ const arg = try leb.readULEB128(usize, &s.stream);
prog.file = arg;
},
DW.LNS_set_column => {
- const arg = try leb.readULEB128(u64, di.dwarf_in_stream);
+ const arg = try leb.readULEB128(u64, &s.stream);
prog.column = arg;
},
DW.LNS_negate_stmt => {
@@ -1696,14 +1637,14 @@ pub const DwarfInfo = struct {
prog.address += inc_addr;
},
DW.LNS_fixed_advance_pc => {
- const arg = try di.dwarf_in_stream.readInt(u16, di.endian);
+ const arg = try s.stream.readInt(u16, di.endian);
prog.address += arg;
},
DW.LNS_set_prologue_end => {},
else => {
if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;
const len_bytes = standard_opcode_lengths[opcode - 1];
- try di.dwarf_seekable_stream.seekBy(len_bytes);
+ try s.seekable_stream.seekBy(len_bytes);
},
}
}
@@ -1713,9 +1654,17 @@ pub const DwarfInfo = struct {
}
fn getString(di: *DwarfInfo, offset: u64) ![]u8 {
- const pos = di.debug_str.offset + offset;
- try di.dwarf_seekable_stream.seekTo(pos);
- return di.readString();
+ if (offset > di.debug_str.len)
+ return error.InvalidDebugInfo;
+ const casted_offset = math.cast(usize, offset) catch
+ return error.InvalidDebugInfo;
+
+ // Valid strings always have a terminating zero byte
+ if (mem.indexOfScalarPos(u8, di.debug_str, casted_offset, 0)) |last| {
+ return di.debug_str[casted_offset..last];
+ }
+
+ return error.InvalidDebugInfo;
}
};
@@ -1727,7 +1676,7 @@ pub const DebugInfo = switch (builtin.os) {
const OFileTable = std.HashMap(
*macho.nlist_64,
- MachOFile,
+ DwarfInfo,
std.hash_map.getHashPtrAddrFn(*macho.nlist_64),
std.hash_map.getTrivialEqlFn(*macho.nlist_64),
);
@@ -1888,6 +1837,7 @@ const LineNumberProgram = struct {
basic_block: bool,
end_sequence: bool,
+ default_is_stmt: bool,
target_address: usize,
include_dirs: []const []const u8,
file_entries: *ArrayList(FileEntry),
@@ -1900,6 +1850,25 @@ const LineNumberProgram = struct {
prev_basic_block: bool,
prev_end_sequence: bool,
+ // Reset the state machine following the DWARF specification
+ pub fn reset(self: *LineNumberProgram) void {
+ self.address = 0;
+ self.file = 1;
+ self.line = 1;
+ self.column = 0;
+ self.is_stmt = self.default_is_stmt;
+ self.basic_block = false;
+ self.end_sequence = false;
+ // Invalidate all the remaining fields
+ self.prev_address = 0;
+ self.prev_file = undefined;
+ self.prev_line = undefined;
+ self.prev_column = undefined;
+ self.prev_is_stmt = undefined;
+ self.prev_basic_block = undefined;
+ self.prev_end_sequence = undefined;
+ }
+
pub fn init(is_stmt: bool, include_dirs: []const []const u8, file_entries: *ArrayList(FileEntry), target_address: usize) LineNumberProgram {
return LineNumberProgram{
.address = 0,
@@ -1911,6 +1880,7 @@ const LineNumberProgram = struct {
.end_sequence = false,
.include_dirs = include_dirs,
.file_entries = file_entries,
+ .default_is_stmt = is_stmt,
.target_address = target_address,
.prev_address = 0,
.prev_file = undefined,
@@ -2100,24 +2070,32 @@ fn getAbbrevTableEntry(abbrev_table: *const AbbrevTable, abbrev_code: u64) ?*con
return null;
}
-fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: usize) !LineInfo {
+fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, address: usize) !LineInfo {
const ofile = symbol.ofile orelse return error.MissingDebugInfo;
const gop = try di.ofiles.getOrPut(ofile);
- const mach_o_file = if (gop.found_existing) &gop.kv.value else blk: {
+ const dwarf_info = if (gop.found_existing) &gop.kv.value else blk: {
errdefer _ = di.ofiles.remove(ofile);
const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx));
- gop.kv.value = MachOFile{
- .bytes = try std.fs.cwd().readFileAllocAligned(
- di.ofiles.allocator,
- ofile_path,
- maxInt(usize),
- @alignOf(macho.mach_header_64),
- ),
- .sect_debug_info = null,
- .sect_debug_line = null,
- };
- const hdr = @ptrCast(*const macho.mach_header_64, gop.kv.value.bytes.ptr);
+ var exe_file = try std.fs.openFileAbsoluteC(ofile_path, .{});
+ errdefer exe_file.close();
+
+ const exe_len = math.cast(usize, try exe_file.getEndPos()) catch
+ return error.DebugInfoTooLarge;
+ const exe_mmap = try os.mmap(
+ null,
+ exe_len,
+ os.PROT_READ,
+ os.MAP_SHARED,
+ exe_file.handle,
+ 0,
+ );
+ errdefer os.munmap(exe_mmap);
+
+ const hdr = @ptrCast(
+ *const macho.mach_header_64,
+ @alignCast(@alignOf(macho.mach_header_64), exe_mmap.ptr),
+ );
if (hdr.magic != std.macho.MH_MAGIC_64) return error.InvalidDebugInfo;
const hdr_base = @ptrCast([*]const u8, hdr);
@@ -2126,181 +2104,75 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
const segcmd = while (ncmd != 0) : (ncmd -= 1) {
const lc = @ptrCast(*const std.macho.load_command, ptr);
switch (lc.cmd) {
- std.macho.LC_SEGMENT_64 => break @ptrCast(*const std.macho.segment_command_64, @alignCast(@alignOf(std.macho.segment_command_64), ptr)),
+ std.macho.LC_SEGMENT_64 => {
+ break @ptrCast(
+ *const std.macho.segment_command_64,
+ @alignCast(@alignOf(std.macho.segment_command_64), ptr),
+ );
+ },
else => {},
}
ptr = @alignCast(@alignOf(std.macho.load_command), ptr + lc.cmdsize);
} else {
return error.MissingDebugInfo;
};
+
+ var opt_debug_line: ?*const macho.section_64 = null;
+ var opt_debug_info: ?*const macho.section_64 = null;
+ var opt_debug_abbrev: ?*const macho.section_64 = null;
+ var opt_debug_str: ?*const macho.section_64 = null;
+ var opt_debug_ranges: ?*const macho.section_64 = null;
+
const sections = @ptrCast([*]const macho.section_64, @alignCast(@alignOf(macho.section_64), ptr + @sizeOf(std.macho.segment_command_64)))[0..segcmd.nsects];
for (sections) |*sect| {
- if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and
- (sect.flags & macho.SECTION_ATTRIBUTES) & macho.S_ATTR_DEBUG == macho.S_ATTR_DEBUG)
- {
- const sect_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, &sect.sectname));
- if (mem.eql(u8, sect_name, "__debug_line")) {
- gop.kv.value.sect_debug_line = sect;
- } else if (mem.eql(u8, sect_name, "__debug_info")) {
- gop.kv.value.sect_debug_info = sect;
- }
+ // The section name may not exceed 16 chars and a trailing null may
+ // not be present
+ const name = if (mem.indexOfScalar(u8, sect.sectname[0..], 0)) |last|
+ sect.sectname[0..last]
+ else
+ sect.sectname[0..];
+
+ if (mem.eql(u8, name, "__debug_line")) {
+ opt_debug_line = sect;
+ } else if (mem.eql(u8, name, "__debug_info")) {
+ opt_debug_info = sect;
+ } else if (mem.eql(u8, name, "__debug_abbrev")) {
+ opt_debug_abbrev = sect;
+ } else if (mem.eql(u8, name, "__debug_str")) {
+ opt_debug_str = sect;
+ } else if (mem.eql(u8, name, "__debug_ranges")) {
+ opt_debug_ranges = sect;
}
}
- break :blk &gop.kv.value;
- };
-
- const sect_debug_line = mach_o_file.sect_debug_line orelse return error.MissingDebugInfo;
- var ptr = mach_o_file.bytes.ptr + sect_debug_line.offset;
-
- var is_64: bool = undefined;
- const unit_length = try readInitialLengthMem(&ptr, &is_64);
- if (unit_length == 0) return error.MissingDebugInfo;
-
- const version = readIntMem(&ptr, u16, builtin.Endian.Little);
- // TODO support 3 and 5
- if (version != 2 and version != 4) return error.InvalidDebugInfo;
-
- const prologue_length = if (is_64)
- readIntMem(&ptr, u64, builtin.Endian.Little)
- else
- readIntMem(&ptr, u32, builtin.Endian.Little);
- const prog_start = ptr + prologue_length;
-
- const minimum_instruction_length = readByteMem(&ptr);
- if (minimum_instruction_length == 0) return error.InvalidDebugInfo;
-
- if (version >= 4) {
- // maximum_operations_per_instruction
- ptr += 1;
- }
-
- const default_is_stmt = readByteMem(&ptr) != 0;
- const line_base = readByteSignedMem(&ptr);
-
- const line_range = readByteMem(&ptr);
- if (line_range == 0) return error.InvalidDebugInfo;
-
- const opcode_base = readByteMem(&ptr);
-
- const standard_opcode_lengths = ptr[0 .. opcode_base - 1];
- ptr += opcode_base - 1;
-
- var include_directories = ArrayList([]const u8).init(di.allocator());
- try include_directories.append("");
- while (true) {
- const dir = readStringMem(&ptr);
- if (dir.len == 0) break;
- try include_directories.append(dir);
- }
-
- var file_entries = ArrayList(FileEntry).init(di.allocator());
- var prog = LineNumberProgram.init(default_is_stmt, include_directories.toSliceConst(), &file_entries, target_address);
+ var debug_line = opt_debug_line orelse
+ return error.MissingDebugInfo;
+ var debug_info = opt_debug_info orelse
+ return error.MissingDebugInfo;
+ var debug_str = opt_debug_str orelse
+ return error.MissingDebugInfo;
+ var debug_abbrev = opt_debug_abbrev orelse
+ return error.MissingDebugInfo;
- while (true) {
- const file_name = readStringMem(&ptr);
- if (file_name.len == 0) break;
- const dir_index = try leb.readULEB128Mem(usize, &ptr);
- const mtime = try leb.readULEB128Mem(usize, &ptr);
- const len_bytes = try leb.readULEB128Mem(usize, &ptr);
- try file_entries.append(FileEntry{
- .file_name = file_name,
- .dir_index = dir_index,
- .mtime = mtime,
- .len_bytes = len_bytes,
- });
- }
+ gop.kv.value = DwarfInfo{
+ .endian = .Little,
+ .debug_info = exe_mmap[@intCast(usize, debug_info.offset)..@intCast(usize, debug_info.offset + debug_info.size)],
+ .debug_abbrev = exe_mmap[@intCast(usize, debug_abbrev.offset)..@intCast(usize, debug_abbrev.offset + debug_abbrev.size)],
+ .debug_str = exe_mmap[@intCast(usize, debug_str.offset)..@intCast(usize, debug_str.offset + debug_str.size)],
+ .debug_line = exe_mmap[@intCast(usize, debug_line.offset)..@intCast(usize, debug_line.offset + debug_line.size)],
+ .debug_ranges = if (opt_debug_ranges) |debug_ranges|
+ exe_mmap[@intCast(usize, debug_ranges.offset)..@intCast(usize, debug_ranges.offset + debug_ranges.size)]
+ else
+ null,
+ };
+ try openDwarfDebugInfo(&gop.kv.value, di.allocator());
- ptr = prog_start;
- while (true) {
- const opcode = readByteMem(&ptr);
-
- if (opcode == DW.LNS_extended_op) {
- const op_size = try leb.readULEB128Mem(u64, &ptr);
- if (op_size < 1) return error.InvalidDebugInfo;
- var sub_op = readByteMem(&ptr);
- switch (sub_op) {
- DW.LNE_end_sequence => {
- prog.end_sequence = true;
- if (try prog.checkLineMatch()) |info| return info;
- return error.MissingDebugInfo;
- },
- DW.LNE_set_address => {
- const addr = readIntMem(&ptr, usize, builtin.Endian.Little);
- prog.address = symbol.reloc + addr;
- },
- DW.LNE_define_file => {
- const file_name = readStringMem(&ptr);
- const dir_index = try leb.readULEB128Mem(usize, &ptr);
- const mtime = try leb.readULEB128Mem(usize, &ptr);
- const len_bytes = try leb.readULEB128Mem(usize, &ptr);
- try file_entries.append(FileEntry{
- .file_name = file_name,
- .dir_index = dir_index,
- .mtime = mtime,
- .len_bytes = len_bytes,
- });
- },
- else => {
- ptr += op_size - 1;
- },
- }
- } else if (opcode >= opcode_base) {
- // special opcodes
- const adjusted_opcode = opcode - opcode_base;
- const inc_addr = minimum_instruction_length * (adjusted_opcode / line_range);
- const inc_line = @as(i32, line_base) + @as(i32, adjusted_opcode % line_range);
- prog.line += inc_line;
- prog.address += inc_addr;
- if (try prog.checkLineMatch()) |info| return info;
- prog.basic_block = false;
- } else {
- switch (opcode) {
- DW.LNS_copy => {
- if (try prog.checkLineMatch()) |info| return info;
- prog.basic_block = false;
- },
- DW.LNS_advance_pc => {
- const arg = try leb.readULEB128Mem(usize, &ptr);
- prog.address += arg * minimum_instruction_length;
- },
- DW.LNS_advance_line => {
- const arg = try leb.readILEB128Mem(i64, &ptr);
- prog.line += arg;
- },
- DW.LNS_set_file => {
- const arg = try leb.readULEB128Mem(usize, &ptr);
- prog.file = arg;
- },
- DW.LNS_set_column => {
- const arg = try leb.readULEB128Mem(u64, &ptr);
- prog.column = arg;
- },
- DW.LNS_negate_stmt => {
- prog.is_stmt = !prog.is_stmt;
- },
- DW.LNS_set_basic_block => {
- prog.basic_block = true;
- },
- DW.LNS_const_add_pc => {
- const inc_addr = minimum_instruction_length * ((255 - opcode_base) / line_range);
- prog.address += inc_addr;
- },
- DW.LNS_fixed_advance_pc => {
- const arg = readIntMem(&ptr, u16, builtin.Endian.Little);
- prog.address += arg;
- },
- DW.LNS_set_prologue_end => {},
- else => {
- if (opcode - 1 >= standard_opcode_lengths.len) return error.InvalidDebugInfo;
- const len_bytes = standard_opcode_lengths[opcode - 1];
- ptr += len_bytes;
- },
- }
- }
- }
+ break :blk &gop.kv.value;
+ };
- return error.MissingDebugInfo;
+ const o_file_address = address - symbol.reloc;
+ const compile_unit = try dwarf_info.findCompileUnit(o_file_address);
+ return dwarf_info.getLineNumberInfo(compile_unit.*, o_file_address);
}
const Func = struct {
@@ -2308,47 +2180,6 @@ const Func = struct {
name: ?[]u8,
};
-fn readIntMem(ptr: *[*]const u8, comptime T: type, endian: builtin.Endian) T {
- // TODO https://github.com/ziglang/zig/issues/863
- const size = (T.bit_count + 7) / 8;
- const result = mem.readIntSlice(T, ptr.*[0..size], endian);
- ptr.* += size;
- return result;
-}
-
-fn readByteMem(ptr: *[*]const u8) u8 {
- const result = ptr.*[0];
- ptr.* += 1;
- return result;
-}
-
-fn readByteSignedMem(ptr: *[*]const u8) i8 {
- return @bitCast(i8, readByteMem(ptr));
-}
-
-fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
- // TODO this code can be improved with https://github.com/ziglang/zig/issues/863
- const first_32_bits = mem.readIntSliceLittle(u32, ptr.*[0..4]);
- is_64.* = (first_32_bits == 0xffffffff);
- if (is_64.*) {
- ptr.* += 4;
- const result = mem.readIntSliceLittle(u64, ptr.*[0..8]);
- ptr.* += 8;
- return result;
- } else {
- if (first_32_bits >= 0xfffffff0) return error.InvalidDebugInfo;
- ptr.* += 4;
- // TODO this cast should not be needed
- return @as(u64, first_32_bits);
- }
-}
-
-fn readStringMem(ptr: *[*]const u8) [:0]const u8 {
- const result = mem.toSliceConst(u8, @ptrCast([*:0]const u8, ptr.*));
- ptr.* += result.len + 1;
- return result;
-}
-
fn readInitialLength(comptime E: type, in_stream: *io.InStream(E), is_64: *bool) !u64 {
const first_32_bits = try in_stream.readIntLittle(u32);
is_64.* = (first_32_bits == 0xffffffff);
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
index 5a650c3b10..cf3322a995 100644
--- a/lib/std/fmt.zig
+++ b/lib/std/fmt.zig
@@ -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..];
diff --git a/lib/std/fmt/parse_float.zig b/lib/std/fmt/parse_float.zig
index 2c480852ac..1456dd8e57 100644
--- a/lib/std/fmt/parse_float.zig
+++ b/lib/std/fmt/parse_float.zig
@@ -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;
diff --git a/lib/std/hash/murmur.zig b/lib/std/hash/murmur.zig
index f6c0ccafb3..23b11ef284 100644
--- a/lib/std/hash/murmur.zig
+++ b/lib/std/hash/murmur.zig
@@ -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);
diff --git a/lib/std/http/headers.zig b/lib/std/http/headers.zig
index b1d047aeec..dfe53fe750 100644
--- a/lib/std/http/headers.zig
+++ b/lib/std/http/headers.zig
@@ -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);
}
diff --git a/lib/std/io/out_stream.zig b/lib/std/io/out_stream.zig
index b8f5db6fff..265be066a1 100644
--- a/lib/std/io/out_stream.zig
+++ b/lib/std/io/out_stream.zig
@@ -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;
}
}
diff --git a/lib/std/io/test.zig b/lib/std/io/test.zig
index 92259fd6e9..21ebd723c4 100644
--- a/lib/std/io/test.zig
+++ b/lib/std/io/test.zig
@@ -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);
diff --git a/lib/std/math/fabs.zig b/lib/std/math/fabs.zig
index a659e35ca2..61692283e6 100644
--- a/lib/std/math/fabs.zig
+++ b/lib/std/math/fabs.zig
@@ -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))));
diff --git a/lib/std/math/isinf.zig b/lib/std/math/isinf.zig
index 6eacab52ad..eeac61915c 100644
--- a/lib/std/math/isinf.zig
+++ b/lib/std/math/isinf.zig
@@ -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)));
diff --git a/lib/std/math/isnan.zig b/lib/std/math/isnan.zig
index ac865f0d0c..4b7e69490a 100644
--- a/lib/std/math/isnan.zig
+++ b/lib/std/math/isnan.zig
@@ -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)));
diff --git a/lib/std/mem.zig b/lib/std/mem.zig
index f7b2bf261d..46f23c84fe 100644
--- a/lib/std/mem.zig
+++ b/lib/std/mem.zig
@@ -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);
}
diff --git a/lib/std/meta.zig b/lib/std/meta.zig
index 5e5850e393..5cb9c6589c 100644
--- a/lib/std/meta.zig
+++ b/lib/std/meta.zig
@@ -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;
+ }
+}
diff --git a/lib/std/os.zig b/lib/std/os.zig
index c39891c6b0..f881d74835 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -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,
diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig
index fcc1e62489..5c25b4369c 100644
--- a/lib/std/os/linux.zig
+++ b/lib/std/os/linux.zig
@@ -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));
}
diff --git a/lib/std/os/linux/tls.zig b/lib/std/os/linux/tls.zig
index efb1e5fe04..5dbdafb60a 100644
--- a/lib/std/os/linux/tls.zig
+++ b/lib/std/os/linux/tls.zig
@@ -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.
diff --git a/lib/std/os/test.zig b/lib/std/os/test.zig
index 1e51dd6f82..f71e80c7d7 100644
--- a/lib/std/os/test.zig
+++ b/lib/std/os/test.zig
@@ -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
diff --git a/lib/std/sort.zig b/lib/std/sort.zig
index 9fa7803cba..98bac0678d 100644
--- a/lib/std/sort.zig
+++ b/lib/std/sort.zig
@@ -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;
}
}
diff --git a/lib/std/special/compiler_rt.zig b/lib/std/special/compiler_rt.zig
index 90dbf0cdf4..f5e83b5278 100644
--- a/lib/std/special/compiler_rt.zig
+++ b/lib/std/special/compiler_rt.zig
@@ -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 });
diff --git a/lib/std/special/compiler_rt/addXf3_test.zig b/lib/std/special/compiler_rt/addXf3_test.zig
index af991b37e9..402bb5a43c 100644
--- a/lib/std/special/compiler_rt/addXf3_test.zig
+++ b/lib/std/special/compiler_rt/addXf3_test.zig
@@ -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);
diff --git a/lib/std/special/compiler_rt/fixtfdi_test.zig b/lib/std/special/compiler_rt/fixtfdi_test.zig
index 6baa9011c3..4c43c90550 100644
--- a/lib/std/special/compiler_rt/fixtfdi_test.zig
+++ b/lib/std/special/compiler_rt/fixtfdi_test.zig
@@ -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));
diff --git a/lib/std/special/compiler_rt/fixtfsi_test.zig b/lib/std/special/compiler_rt/fixtfsi_test.zig
index c7294fe250..4eabd0c594 100644
--- a/lib/std/special/compiler_rt/fixtfsi_test.zig
+++ b/lib/std/special/compiler_rt/fixtfsi_test.zig
@@ -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));
diff --git a/lib/std/special/compiler_rt/fixtfti_test.zig b/lib/std/special/compiler_rt/fixtfti_test.zig
index 6b8218e2f6..acda2f162b 100644
--- a/lib/std/special/compiler_rt/fixtfti_test.zig
+++ b/lib/std/special/compiler_rt/fixtfti_test.zig
@@ -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));
diff --git a/lib/std/special/compiler_rt/fixunstfdi_test.zig b/lib/std/special/compiler_rt/fixunstfdi_test.zig
index 0d47641c09..154fffe18a 100644
--- a/lib/std/special/compiler_rt/fixunstfdi_test.zig
+++ b/lib/std/special/compiler_rt/fixunstfdi_test.zig
@@ -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);
diff --git a/lib/std/special/compiler_rt/fixunstfsi_test.zig b/lib/std/special/compiler_rt/fixunstfsi_test.zig
index 286567629a..af312ddc46 100644
--- a/lib/std/special/compiler_rt/fixunstfsi_test.zig
+++ b/lib/std/special/compiler_rt/fixunstfsi_test.zig
@@ -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);
diff --git a/lib/std/special/compiler_rt/fixunstfti_test.zig b/lib/std/special/compiler_rt/fixunstfti_test.zig
index 62a9bbfecf..84dbf991e2 100644
--- a/lib/std/special/compiler_rt/fixunstfti_test.zig
+++ b/lib/std/special/compiler_rt/fixunstfti_test.zig
@@ -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);
diff --git a/lib/std/special/compiler_rt/floattitf_test.zig b/lib/std/special/compiler_rt/floattitf_test.zig
index 53e3e48bdb..0b2b5b958a 100644
--- a/lib/std/special/compiler_rt/floattitf_test.zig
+++ b/lib/std/special/compiler_rt/floattitf_test.zig
@@ -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);
diff --git a/lib/std/special/compiler_rt/floatuntitf_test.zig b/lib/std/special/compiler_rt/floatuntitf_test.zig
index 09f3eabb3e..8b99bbef5d 100644
--- a/lib/std/special/compiler_rt/floatuntitf_test.zig
+++ b/lib/std/special/compiler_rt/floatuntitf_test.zig
@@ -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);
diff --git a/lib/std/special/compiler_rt/int.zig b/lib/std/special/compiler_rt/int.zig
index 88f4d66966..eb731ee898 100644
--- a/lib/std/special/compiler_rt/int.zig
+++ b/lib/std/special/compiler_rt/int.zig
@@ -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));
+}
diff --git a/lib/std/special/compiler_rt/mulXf3_test.zig b/lib/std/special/compiler_rt/mulXf3_test.zig
index 57dc385321..00db984a89 100644
--- a/lib/std/special/compiler_rt/mulXf3_test.zig
+++ b/lib/std/special/compiler_rt/mulXf3_test.zig
@@ -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);
diff --git a/lib/std/special/compiler_rt/truncXfYf2_test.zig b/lib/std/special/compiler_rt/truncXfYf2_test.zig
index baec2a4450..f14dbe6b43 100644
--- a/lib/std/special/compiler_rt/truncXfYf2_test.zig
+++ b/lib/std/special/compiler_rt/truncXfYf2_test.zig
@@ -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
diff --git a/lib/std/target.zig b/lib/std/target.zig
index 42cbe6c7fc..09f56dcb87 100644
--- a/lib/std/target.zig
+++ b/lib/std/target.zig
@@ -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));
+}
diff --git a/lib/std/target/aarch64.zig b/lib/std/target/aarch64.zig
new file mode 100644
index 0000000000..d2878e2423
--- /dev/null
+++ b/lib/std/target/aarch64.zig
@@ -0,0 +1,1450 @@
+const std = @import("../std.zig");
+const Cpu = std.Target.Cpu;
+
+pub const Feature = enum {
+ a35,
+ a53,
+ a55,
+ a57,
+ a72,
+ a73,
+ a75,
+ a76,
+ aes,
+ aggressive_fma,
+ alternate_sextload_cvt_f32_pattern,
+ altnzcv,
+ am,
+ arith_bcc_fusion,
+ arith_cbz_fusion,
+ balance_fp_ops,
+ bti,
+ call_saved_x10,
+ call_saved_x11,
+ call_saved_x12,
+ call_saved_x13,
+ call_saved_x14,
+ call_saved_x15,
+ call_saved_x18,
+ call_saved_x8,
+ call_saved_x9,
+ ccdp,
+ ccidx,
+ ccpp,
+ complxnum,
+ crc,
+ crypto,
+ custom_cheap_as_move,
+ cyclone,
+ disable_latency_sched_heuristic,
+ dit,
+ dotprod,
+ exynos_cheap_as_move,
+ exynosm1,
+ exynosm2,
+ exynosm3,
+ exynosm4,
+ falkor,
+ fmi,
+ force_32bit_jump_tables,
+ fp_armv8,
+ fp16fml,
+ fptoint,
+ fullfp16,
+ fuse_address,
+ fuse_aes,
+ fuse_arith_logic,
+ fuse_crypto_eor,
+ fuse_csel,
+ fuse_literals,
+ jsconv,
+ kryo,
+ lor,
+ lse,
+ lsl_fast,
+ mpam,
+ mte,
+ neon,
+ no_neg_immediates,
+ nv,
+ pa,
+ pan,
+ pan_rwv,
+ perfmon,
+ predictable_select_expensive,
+ predres,
+ rand,
+ ras,
+ rasv8_4,
+ rcpc,
+ rcpc_immo,
+ rdm,
+ reserve_x1,
+ reserve_x10,
+ reserve_x11,
+ reserve_x12,
+ reserve_x13,
+ reserve_x14,
+ reserve_x15,
+ reserve_x18,
+ reserve_x2,
+ reserve_x20,
+ reserve_x21,
+ reserve_x22,
+ reserve_x23,
+ reserve_x24,
+ reserve_x25,
+ reserve_x26,
+ reserve_x27,
+ reserve_x28,
+ reserve_x3,
+ reserve_x4,
+ reserve_x5,
+ reserve_x6,
+ reserve_x7,
+ reserve_x9,
+ saphira,
+ sb,
+ sel2,
+ sha2,
+ sha3,
+ slow_misaligned_128store,
+ slow_paired_128,
+ slow_strqro_store,
+ sm4,
+ spe,
+ specrestrict,
+ ssbs,
+ strict_align,
+ sve,
+ sve2,
+ sve2_aes,
+ sve2_bitperm,
+ sve2_sha3,
+ sve2_sm4,
+ thunderx,
+ thunderx2t99,
+ thunderxt81,
+ thunderxt83,
+ thunderxt88,
+ tlb_rmi,
+ tpidr_el1,
+ tpidr_el2,
+ tpidr_el3,
+ tracev8_4,
+ tsv110,
+ uaops,
+ use_aa,
+ use_postra_scheduler,
+ use_reciprocal_square_root,
+ v8a,
+ v8_1a,
+ v8_2a,
+ v8_3a,
+ v8_4a,
+ v8_5a,
+ vh,
+ zcm,
+ zcz,
+ zcz_fp,
+ zcz_fp_workaround,
+ zcz_gp,
+};
+
+pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+
+pub const all_features = blk: {
+ @setEvalBranchQuota(2000);
+ 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.a35)] = .{
+ .llvm_name = "a35",
+ .description = "Cortex-A35 ARM processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .fp_armv8,
+ .neon,
+ .perfmon,
+ }),
+ };
+ result[@enumToInt(Feature.a53)] = .{
+ .llvm_name = "a53",
+ .description = "Cortex-A53 ARM processors",
+ .dependencies = featureSet(&[_]Feature{
+ .balance_fp_ops,
+ .crc,
+ .crypto,
+ .custom_cheap_as_move,
+ .fp_armv8,
+ .fuse_aes,
+ .neon,
+ .perfmon,
+ .use_aa,
+ .use_postra_scheduler,
+ }),
+ };
+ result[@enumToInt(Feature.a55)] = .{
+ .llvm_name = "a55",
+ .description = "Cortex-A55 ARM processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crypto,
+ .dotprod,
+ .fp_armv8,
+ .fullfp16,
+ .fuse_aes,
+ .neon,
+ .perfmon,
+ .rcpc,
+ .v8_2a,
+ }),
+ };
+ result[@enumToInt(Feature.a57)] = .{
+ .llvm_name = "a57",
+ .description = "Cortex-A57 ARM processors",
+ .dependencies = featureSet(&[_]Feature{
+ .balance_fp_ops,
+ .crc,
+ .crypto,
+ .custom_cheap_as_move,
+ .fp_armv8,
+ .fuse_aes,
+ .fuse_literals,
+ .neon,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ }),
+ };
+ result[@enumToInt(Feature.a72)] = .{
+ .llvm_name = "a72",
+ .description = "Cortex-A72 ARM processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .fp_armv8,
+ .fuse_aes,
+ .neon,
+ .perfmon,
+ }),
+ };
+ result[@enumToInt(Feature.a73)] = .{
+ .llvm_name = "a73",
+ .description = "Cortex-A73 ARM processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .fp_armv8,
+ .fuse_aes,
+ .neon,
+ .perfmon,
+ }),
+ };
+ result[@enumToInt(Feature.a75)] = .{
+ .llvm_name = "a75",
+ .description = "Cortex-A75 ARM processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crypto,
+ .dotprod,
+ .fp_armv8,
+ .fullfp16,
+ .fuse_aes,
+ .neon,
+ .perfmon,
+ .rcpc,
+ .v8_2a,
+ }),
+ };
+ result[@enumToInt(Feature.a76)] = .{
+ .llvm_name = "a76",
+ .description = "Cortex-A76 ARM processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crypto,
+ .dotprod,
+ .fp_armv8,
+ .fullfp16,
+ .neon,
+ .rcpc,
+ .ssbs,
+ .v8_2a,
+ }),
+ };
+ result[@enumToInt(Feature.aes)] = .{
+ .llvm_name = "aes",
+ .description = "Enable AES support",
+ .dependencies = featureSet(&[_]Feature{
+ .neon,
+ }),
+ };
+ result[@enumToInt(Feature.aggressive_fma)] = .{
+ .llvm_name = "aggressive-fma",
+ .description = "Enable Aggressive FMA for floating-point.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.alternate_sextload_cvt_f32_pattern)] = .{
+ .llvm_name = "alternate-sextload-cvt-f32-pattern",
+ .description = "Use alternative pattern for sextload convert to f32",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.altnzcv)] = .{
+ .llvm_name = "altnzcv",
+ .description = "Enable alternative NZCV format for floating point comparisons",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.am)] = .{
+ .llvm_name = "am",
+ .description = "Enable v8.4-A Activity Monitors extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.arith_bcc_fusion)] = .{
+ .llvm_name = "arith-bcc-fusion",
+ .description = "CPU fuses arithmetic+bcc operations",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.arith_cbz_fusion)] = .{
+ .llvm_name = "arith-cbz-fusion",
+ .description = "CPU fuses arithmetic + cbz/cbnz operations",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.balance_fp_ops)] = .{
+ .llvm_name = "balance-fp-ops",
+ .description = "balance mix of odd and even D-registers for fp multiply(-accumulate) ops",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.bti)] = .{
+ .llvm_name = "bti",
+ .description = "Enable Branch Target Identification",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.call_saved_x10)] = .{
+ .llvm_name = "call-saved-x10",
+ .description = "Make X10 callee saved.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.call_saved_x11)] = .{
+ .llvm_name = "call-saved-x11",
+ .description = "Make X11 callee saved.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.call_saved_x12)] = .{
+ .llvm_name = "call-saved-x12",
+ .description = "Make X12 callee saved.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.call_saved_x13)] = .{
+ .llvm_name = "call-saved-x13",
+ .description = "Make X13 callee saved.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.call_saved_x14)] = .{
+ .llvm_name = "call-saved-x14",
+ .description = "Make X14 callee saved.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.call_saved_x15)] = .{
+ .llvm_name = "call-saved-x15",
+ .description = "Make X15 callee saved.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.call_saved_x18)] = .{
+ .llvm_name = "call-saved-x18",
+ .description = "Make X18 callee saved.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.call_saved_x8)] = .{
+ .llvm_name = "call-saved-x8",
+ .description = "Make X8 callee saved.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.call_saved_x9)] = .{
+ .llvm_name = "call-saved-x9",
+ .description = "Make X9 callee saved.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ccdp)] = .{
+ .llvm_name = "ccdp",
+ .description = "Enable v8.5 Cache Clean to Point of Deep Persistence",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ccidx)] = .{
+ .llvm_name = "ccidx",
+ .description = "Enable v8.3-A Extend of the CCSIDR number of sets",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ccpp)] = .{
+ .llvm_name = "ccpp",
+ .description = "Enable v8.2 data Cache Clean to Point of Persistence",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.complxnum)] = .{
+ .llvm_name = "complxnum",
+ .description = "Enable v8.3-A Floating-point complex number support",
+ .dependencies = featureSet(&[_]Feature{
+ .neon,
+ }),
+ };
+ result[@enumToInt(Feature.crc)] = .{
+ .llvm_name = "crc",
+ .description = "Enable ARMv8 CRC-32 checksum instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.crypto)] = .{
+ .llvm_name = "crypto",
+ .description = "Enable cryptographic instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .aes,
+ .neon,
+ .sha2,
+ }),
+ };
+ result[@enumToInt(Feature.custom_cheap_as_move)] = .{
+ .llvm_name = "custom-cheap-as-move",
+ .description = "Use custom handling of cheap instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.cyclone)] = .{
+ .llvm_name = "cyclone",
+ .description = "Cyclone",
+ .dependencies = featureSet(&[_]Feature{
+ .alternate_sextload_cvt_f32_pattern,
+ .arith_bcc_fusion,
+ .arith_cbz_fusion,
+ .crypto,
+ .disable_latency_sched_heuristic,
+ .fp_armv8,
+ .fuse_aes,
+ .fuse_crypto_eor,
+ .neon,
+ .perfmon,
+ .zcm,
+ .zcz,
+ .zcz_fp_workaround,
+ }),
+ };
+ result[@enumToInt(Feature.disable_latency_sched_heuristic)] = .{
+ .llvm_name = "disable-latency-sched-heuristic",
+ .description = "Disable latency scheduling heuristic",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dit)] = .{
+ .llvm_name = "dit",
+ .description = "Enable v8.4-A Data Independent Timing instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dotprod)] = .{
+ .llvm_name = "dotprod",
+ .description = "Enable dot product support",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.exynos_cheap_as_move)] = .{
+ .llvm_name = "exynos-cheap-as-move",
+ .description = "Use Exynos specific handling of cheap instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .custom_cheap_as_move,
+ }),
+ };
+ result[@enumToInt(Feature.exynosm1)] = .{
+ .llvm_name = "exynosm1",
+ .description = "Samsung Exynos-M1 processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .exynos_cheap_as_move,
+ .force_32bit_jump_tables,
+ .fuse_aes,
+ .perfmon,
+ .slow_misaligned_128store,
+ .slow_paired_128,
+ .use_postra_scheduler,
+ .use_reciprocal_square_root,
+ .zcz_fp,
+ }),
+ };
+ result[@enumToInt(Feature.exynosm2)] = .{
+ .llvm_name = "exynosm2",
+ .description = "Samsung Exynos-M2 processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .exynos_cheap_as_move,
+ .force_32bit_jump_tables,
+ .fuse_aes,
+ .perfmon,
+ .slow_misaligned_128store,
+ .slow_paired_128,
+ .use_postra_scheduler,
+ .zcz_fp,
+ }),
+ };
+ result[@enumToInt(Feature.exynosm3)] = .{
+ .llvm_name = "exynosm3",
+ .description = "Samsung Exynos-M3 processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .exynos_cheap_as_move,
+ .force_32bit_jump_tables,
+ .fuse_address,
+ .fuse_aes,
+ .fuse_csel,
+ .fuse_literals,
+ .lsl_fast,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ .zcz_fp,
+ }),
+ };
+ result[@enumToInt(Feature.exynosm4)] = .{
+ .llvm_name = "exynosm4",
+ .description = "Samsung Exynos-M4 processors",
+ .dependencies = featureSet(&[_]Feature{
+ .arith_bcc_fusion,
+ .arith_cbz_fusion,
+ .crypto,
+ .dotprod,
+ .exynos_cheap_as_move,
+ .force_32bit_jump_tables,
+ .fullfp16,
+ .fuse_address,
+ .fuse_aes,
+ .fuse_arith_logic,
+ .fuse_csel,
+ .fuse_literals,
+ .lsl_fast,
+ .perfmon,
+ .use_postra_scheduler,
+ .v8_2a,
+ .zcz,
+ }),
+ };
+ result[@enumToInt(Feature.falkor)] = .{
+ .llvm_name = "falkor",
+ .description = "Qualcomm Falkor processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .custom_cheap_as_move,
+ .fp_armv8,
+ .lsl_fast,
+ .neon,
+ .perfmon,
+ .predictable_select_expensive,
+ .rdm,
+ .slow_strqro_store,
+ .use_postra_scheduler,
+ .zcz,
+ }),
+ };
+ result[@enumToInt(Feature.fmi)] = .{
+ .llvm_name = "fmi",
+ .description = "Enable v8.4-A Flag Manipulation Instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.force_32bit_jump_tables)] = .{
+ .llvm_name = "force-32bit-jump-tables",
+ .description = "Force jump table entries to be 32-bits wide except at MinSize",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fp_armv8)] = .{
+ .llvm_name = "fp-armv8",
+ .description = "Enable ARMv8 FP",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fp16fml)] = .{
+ .llvm_name = "fp16fml",
+ .description = "Enable FP16 FML instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .fullfp16,
+ }),
+ };
+ result[@enumToInt(Feature.fptoint)] = .{
+ .llvm_name = "fptoint",
+ .description = "Enable FRInt[32|64][Z|X] instructions that round a floating-point number to an integer (in FP format) forcing it to fit into a 32- or 64-bit int",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fullfp16)] = .{
+ .llvm_name = "fullfp16",
+ .description = "Full FP16",
+ .dependencies = featureSet(&[_]Feature{
+ .fp_armv8,
+ }),
+ };
+ result[@enumToInt(Feature.fuse_address)] = .{
+ .llvm_name = "fuse-address",
+ .description = "CPU fuses address generation and memory operations",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fuse_aes)] = .{
+ .llvm_name = "fuse-aes",
+ .description = "CPU fuses AES crypto operations",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fuse_arith_logic)] = .{
+ .llvm_name = "fuse-arith-logic",
+ .description = "CPU fuses arithmetic and logic operations",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fuse_crypto_eor)] = .{
+ .llvm_name = "fuse-crypto-eor",
+ .description = "CPU fuses AES/PMULL and EOR operations",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fuse_csel)] = .{
+ .llvm_name = "fuse-csel",
+ .description = "CPU fuses conditional select operations",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fuse_literals)] = .{
+ .llvm_name = "fuse-literals",
+ .description = "CPU fuses literal generation operations",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.jsconv)] = .{
+ .llvm_name = "jsconv",
+ .description = "Enable v8.3-A JavaScript FP conversion enchancement",
+ .dependencies = featureSet(&[_]Feature{
+ .fp_armv8,
+ }),
+ };
+ result[@enumToInt(Feature.kryo)] = .{
+ .llvm_name = "kryo",
+ .description = "Qualcomm Kryo processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .custom_cheap_as_move,
+ .fp_armv8,
+ .lsl_fast,
+ .neon,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ .zcz,
+ }),
+ };
+ result[@enumToInt(Feature.lor)] = .{
+ .llvm_name = "lor",
+ .description = "Enables ARM v8.1 Limited Ordering Regions extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.lse)] = .{
+ .llvm_name = "lse",
+ .description = "Enable ARMv8.1 Large System Extension (LSE) atomic instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.lsl_fast)] = .{
+ .llvm_name = "lsl-fast",
+ .description = "CPU has a fastpath logical shift of up to 3 places",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.mpam)] = .{
+ .llvm_name = "mpam",
+ .description = "Enable v8.4-A Memory system Partitioning and Monitoring extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.mte)] = .{
+ .llvm_name = "mte",
+ .description = "Enable Memory Tagging Extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.neon)] = .{
+ .llvm_name = "neon",
+ .description = "Enable Advanced SIMD instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .fp_armv8,
+ }),
+ };
+ result[@enumToInt(Feature.no_neg_immediates)] = .{
+ .llvm_name = "no-neg-immediates",
+ .description = "Convert immediates and instructions to their negated or complemented equivalent when the immediate does not fit in the encoding.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.nv)] = .{
+ .llvm_name = "nv",
+ .description = "Enable v8.4-A Nested Virtualization Enchancement",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.pa)] = .{
+ .llvm_name = "pa",
+ .description = "Enable v8.3-A Pointer Authentication enchancement",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.pan)] = .{
+ .llvm_name = "pan",
+ .description = "Enables ARM v8.1 Privileged Access-Never extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.pan_rwv)] = .{
+ .llvm_name = "pan-rwv",
+ .description = "Enable v8.2 PAN s1e1R and s1e1W Variants",
+ .dependencies = featureSet(&[_]Feature{
+ .pan,
+ }),
+ };
+ result[@enumToInt(Feature.perfmon)] = .{
+ .llvm_name = "perfmon",
+ .description = "Enable ARMv8 PMUv3 Performance Monitors extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.predictable_select_expensive)] = .{
+ .llvm_name = "predictable-select-expensive",
+ .description = "Prefer likely predicted branches over selects",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.predres)] = .{
+ .llvm_name = "predres",
+ .description = "Enable v8.5a execution and data prediction invalidation instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.rand)] = .{
+ .llvm_name = "rand",
+ .description = "Enable Random Number generation instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ras)] = .{
+ .llvm_name = "ras",
+ .description = "Enable ARMv8 Reliability, Availability and Serviceability Extensions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.rasv8_4)] = .{
+ .llvm_name = "rasv8_4",
+ .description = "Enable v8.4-A Reliability, Availability and Serviceability extension",
+ .dependencies = featureSet(&[_]Feature{
+ .ras,
+ }),
+ };
+ result[@enumToInt(Feature.rcpc)] = .{
+ .llvm_name = "rcpc",
+ .description = "Enable support for RCPC extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.rcpc_immo)] = .{
+ .llvm_name = "rcpc-immo",
+ .description = "Enable v8.4-A RCPC instructions with Immediate Offsets",
+ .dependencies = featureSet(&[_]Feature{
+ .rcpc,
+ }),
+ };
+ result[@enumToInt(Feature.rdm)] = .{
+ .llvm_name = "rdm",
+ .description = "Enable ARMv8.1 Rounding Double Multiply Add/Subtract instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x1)] = .{
+ .llvm_name = "reserve-x1",
+ .description = "Reserve X1, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x10)] = .{
+ .llvm_name = "reserve-x10",
+ .description = "Reserve X10, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x11)] = .{
+ .llvm_name = "reserve-x11",
+ .description = "Reserve X11, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x12)] = .{
+ .llvm_name = "reserve-x12",
+ .description = "Reserve X12, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x13)] = .{
+ .llvm_name = "reserve-x13",
+ .description = "Reserve X13, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x14)] = .{
+ .llvm_name = "reserve-x14",
+ .description = "Reserve X14, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x15)] = .{
+ .llvm_name = "reserve-x15",
+ .description = "Reserve X15, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x18)] = .{
+ .llvm_name = "reserve-x18",
+ .description = "Reserve X18, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x2)] = .{
+ .llvm_name = "reserve-x2",
+ .description = "Reserve X2, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x20)] = .{
+ .llvm_name = "reserve-x20",
+ .description = "Reserve X20, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x21)] = .{
+ .llvm_name = "reserve-x21",
+ .description = "Reserve X21, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x22)] = .{
+ .llvm_name = "reserve-x22",
+ .description = "Reserve X22, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x23)] = .{
+ .llvm_name = "reserve-x23",
+ .description = "Reserve X23, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x24)] = .{
+ .llvm_name = "reserve-x24",
+ .description = "Reserve X24, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x25)] = .{
+ .llvm_name = "reserve-x25",
+ .description = "Reserve X25, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x26)] = .{
+ .llvm_name = "reserve-x26",
+ .description = "Reserve X26, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x27)] = .{
+ .llvm_name = "reserve-x27",
+ .description = "Reserve X27, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x28)] = .{
+ .llvm_name = "reserve-x28",
+ .description = "Reserve X28, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x3)] = .{
+ .llvm_name = "reserve-x3",
+ .description = "Reserve X3, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x4)] = .{
+ .llvm_name = "reserve-x4",
+ .description = "Reserve X4, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x5)] = .{
+ .llvm_name = "reserve-x5",
+ .description = "Reserve X5, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x6)] = .{
+ .llvm_name = "reserve-x6",
+ .description = "Reserve X6, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x7)] = .{
+ .llvm_name = "reserve-x7",
+ .description = "Reserve X7, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_x9)] = .{
+ .llvm_name = "reserve-x9",
+ .description = "Reserve X9, making it unavailable as a GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.saphira)] = .{
+ .llvm_name = "saphira",
+ .description = "Qualcomm Saphira processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crypto,
+ .custom_cheap_as_move,
+ .fp_armv8,
+ .lsl_fast,
+ .neon,
+ .perfmon,
+ .predictable_select_expensive,
+ .spe,
+ .use_postra_scheduler,
+ .v8_4a,
+ .zcz,
+ }),
+ };
+ result[@enumToInt(Feature.sb)] = .{
+ .llvm_name = "sb",
+ .description = "Enable v8.5 Speculation Barrier",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sel2)] = .{
+ .llvm_name = "sel2",
+ .description = "Enable v8.4-A Secure Exception Level 2 extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sha2)] = .{
+ .llvm_name = "sha2",
+ .description = "Enable SHA1 and SHA256 support",
+ .dependencies = featureSet(&[_]Feature{
+ .neon,
+ }),
+ };
+ result[@enumToInt(Feature.sha3)] = .{
+ .llvm_name = "sha3",
+ .description = "Enable SHA512 and SHA3 support",
+ .dependencies = featureSet(&[_]Feature{
+ .neon,
+ .sha2,
+ }),
+ };
+ result[@enumToInt(Feature.slow_misaligned_128store)] = .{
+ .llvm_name = "slow-misaligned-128store",
+ .description = "Misaligned 128 bit stores are slow",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_paired_128)] = .{
+ .llvm_name = "slow-paired-128",
+ .description = "Paired 128 bit loads and stores are slow",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_strqro_store)] = .{
+ .llvm_name = "slow-strqro-store",
+ .description = "STR of Q register with register offset is slow",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sm4)] = .{
+ .llvm_name = "sm4",
+ .description = "Enable SM3 and SM4 support",
+ .dependencies = featureSet(&[_]Feature{
+ .neon,
+ }),
+ };
+ result[@enumToInt(Feature.spe)] = .{
+ .llvm_name = "spe",
+ .description = "Enable Statistical Profiling extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.specrestrict)] = .{
+ .llvm_name = "specrestrict",
+ .description = "Enable architectural speculation restriction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ssbs)] = .{
+ .llvm_name = "ssbs",
+ .description = "Enable Speculative Store Bypass Safe bit",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.strict_align)] = .{
+ .llvm_name = "strict-align",
+ .description = "Disallow all unaligned memory access",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sve)] = .{
+ .llvm_name = "sve",
+ .description = "Enable Scalable Vector Extension (SVE) instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sve2)] = .{
+ .llvm_name = "sve2",
+ .description = "Enable Scalable Vector Extension 2 (SVE2) instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sve,
+ }),
+ };
+ result[@enumToInt(Feature.sve2_aes)] = .{
+ .llvm_name = "sve2-aes",
+ .description = "Enable AES SVE2 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .aes,
+ .sve2,
+ }),
+ };
+ result[@enumToInt(Feature.sve2_bitperm)] = .{
+ .llvm_name = "sve2-bitperm",
+ .description = "Enable bit permutation SVE2 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sve2,
+ }),
+ };
+ result[@enumToInt(Feature.sve2_sha3)] = .{
+ .llvm_name = "sve2-sha3",
+ .description = "Enable SHA3 SVE2 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sha3,
+ .sve2,
+ }),
+ };
+ result[@enumToInt(Feature.sve2_sm4)] = .{
+ .llvm_name = "sve2-sm4",
+ .description = "Enable SM4 SVE2 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sm4,
+ .sve2,
+ }),
+ };
+ result[@enumToInt(Feature.thunderx)] = .{
+ .llvm_name = "thunderx",
+ .description = "Cavium ThunderX processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .fp_armv8,
+ .neon,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ }),
+ };
+ result[@enumToInt(Feature.thunderx2t99)] = .{
+ .llvm_name = "thunderx2t99",
+ .description = "Cavium ThunderX2 processors",
+ .dependencies = featureSet(&[_]Feature{
+ .aggressive_fma,
+ .arith_bcc_fusion,
+ .crc,
+ .crypto,
+ .fp_armv8,
+ .lse,
+ .neon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ .v8_1a,
+ }),
+ };
+ result[@enumToInt(Feature.thunderxt81)] = .{
+ .llvm_name = "thunderxt81",
+ .description = "Cavium ThunderX processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .fp_armv8,
+ .neon,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ }),
+ };
+ result[@enumToInt(Feature.thunderxt83)] = .{
+ .llvm_name = "thunderxt83",
+ .description = "Cavium ThunderX processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .fp_armv8,
+ .neon,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ }),
+ };
+ result[@enumToInt(Feature.thunderxt88)] = .{
+ .llvm_name = "thunderxt88",
+ .description = "Cavium ThunderX processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .fp_armv8,
+ .neon,
+ .perfmon,
+ .predictable_select_expensive,
+ .use_postra_scheduler,
+ }),
+ };
+ result[@enumToInt(Feature.tlb_rmi)] = .{
+ .llvm_name = "tlb-rmi",
+ .description = "Enable v8.4-A TLB Range and Maintenance Instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.tpidr_el1)] = .{
+ .llvm_name = "tpidr-el1",
+ .description = "Permit use of TPIDR_EL1 for the TLS base",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.tpidr_el2)] = .{
+ .llvm_name = "tpidr-el2",
+ .description = "Permit use of TPIDR_EL2 for the TLS base",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.tpidr_el3)] = .{
+ .llvm_name = "tpidr-el3",
+ .description = "Permit use of TPIDR_EL3 for the TLS base",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.tracev8_4)] = .{
+ .llvm_name = "tracev8.4",
+ .description = "Enable v8.4-A Trace extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.tsv110)] = .{
+ .llvm_name = "tsv110",
+ .description = "HiSilicon TS-V110 processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crypto,
+ .custom_cheap_as_move,
+ .dotprod,
+ .fp_armv8,
+ .fp16fml,
+ .fullfp16,
+ .fuse_aes,
+ .neon,
+ .perfmon,
+ .spe,
+ .use_postra_scheduler,
+ .v8_2a,
+ }),
+ };
+ result[@enumToInt(Feature.uaops)] = .{
+ .llvm_name = "uaops",
+ .description = "Enable v8.2 UAO PState",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.use_aa)] = .{
+ .llvm_name = "use-aa",
+ .description = "Use alias analysis during codegen",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.use_postra_scheduler)] = .{
+ .llvm_name = "use-postra-scheduler",
+ .description = "Schedule again after register allocation",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.use_reciprocal_square_root)] = .{
+ .llvm_name = "use-reciprocal-square-root",
+ .description = "Use the reciprocal square root approximation",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.v8a)] = .{
+ .llvm_name = null,
+ .description = "Support ARM v8a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .fp_armv8,
+ .neon,
+ }),
+ };
+ result[@enumToInt(Feature.v8_1a)] = .{
+ .llvm_name = "v8.1a",
+ .description = "Support ARM v8.1a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .lor,
+ .lse,
+ .pan,
+ .rdm,
+ .vh,
+ .v8a,
+ }),
+ };
+ result[@enumToInt(Feature.v8_2a)] = .{
+ .llvm_name = "v8.2a",
+ .description = "Support ARM v8.2a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .ccpp,
+ .pan_rwv,
+ .ras,
+ .uaops,
+ .v8_1a,
+ }),
+ };
+ result[@enumToInt(Feature.v8_3a)] = .{
+ .llvm_name = "v8.3a",
+ .description = "Support ARM v8.3a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .ccidx,
+ .complxnum,
+ .jsconv,
+ .pa,
+ .rcpc,
+ .v8_2a,
+ }),
+ };
+ result[@enumToInt(Feature.v8_4a)] = .{
+ .llvm_name = "v8.4a",
+ .description = "Support ARM v8.4a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .am,
+ .dit,
+ .dotprod,
+ .fmi,
+ .mpam,
+ .nv,
+ .rasv8_4,
+ .rcpc_immo,
+ .sel2,
+ .tlb_rmi,
+ .tracev8_4,
+ .v8_3a,
+ }),
+ };
+ result[@enumToInt(Feature.v8_5a)] = .{
+ .llvm_name = "v8.5a",
+ .description = "Support ARM v8.5a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .altnzcv,
+ .bti,
+ .ccdp,
+ .fptoint,
+ .predres,
+ .sb,
+ .specrestrict,
+ .ssbs,
+ .v8_4a,
+ }),
+ };
+ result[@enumToInt(Feature.vh)] = .{
+ .llvm_name = "vh",
+ .description = "Enables ARM v8.1 Virtual Host extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.zcm)] = .{
+ .llvm_name = "zcm",
+ .description = "Has zero-cycle register moves",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.zcz)] = .{
+ .llvm_name = "zcz",
+ .description = "Has zero-cycle zeroing instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .zcz_fp,
+ .zcz_gp,
+ }),
+ };
+ result[@enumToInt(Feature.zcz_fp)] = .{
+ .llvm_name = "zcz-fp",
+ .description = "Has zero-cycle zeroing instructions for FP registers",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.zcz_fp_workaround)] = .{
+ .llvm_name = "zcz-fp-workaround",
+ .description = "The zero-cycle floating-point zeroing instruction has a bug",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.zcz_gp)] = .{
+ .llvm_name = "zcz-gp",
+ .description = "Has zero-cycle zeroing instructions for generic registers",
+ .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 apple_latest = Cpu{
+ .name = "apple_latest",
+ .llvm_name = "apple-latest",
+ .features = featureSet(&[_]Feature{
+ .cyclone,
+ }),
+ };
+ pub const cortex_a35 = Cpu{
+ .name = "cortex_a35",
+ .llvm_name = "cortex-a35",
+ .features = featureSet(&[_]Feature{
+ .a35,
+ }),
+ };
+ pub const cortex_a53 = Cpu{
+ .name = "cortex_a53",
+ .llvm_name = "cortex-a53",
+ .features = featureSet(&[_]Feature{
+ .a53,
+ }),
+ };
+ pub const cortex_a55 = Cpu{
+ .name = "cortex_a55",
+ .llvm_name = "cortex-a55",
+ .features = featureSet(&[_]Feature{
+ .a55,
+ }),
+ };
+ pub const cortex_a57 = Cpu{
+ .name = "cortex_a57",
+ .llvm_name = "cortex-a57",
+ .features = featureSet(&[_]Feature{
+ .a57,
+ }),
+ };
+ pub const cortex_a72 = Cpu{
+ .name = "cortex_a72",
+ .llvm_name = "cortex-a72",
+ .features = featureSet(&[_]Feature{
+ .a72,
+ }),
+ };
+ pub const cortex_a73 = Cpu{
+ .name = "cortex_a73",
+ .llvm_name = "cortex-a73",
+ .features = featureSet(&[_]Feature{
+ .a73,
+ }),
+ };
+ pub const cortex_a75 = Cpu{
+ .name = "cortex_a75",
+ .llvm_name = "cortex-a75",
+ .features = featureSet(&[_]Feature{
+ .a75,
+ }),
+ };
+ pub const cortex_a76 = Cpu{
+ .name = "cortex_a76",
+ .llvm_name = "cortex-a76",
+ .features = featureSet(&[_]Feature{
+ .a76,
+ }),
+ };
+ pub const cortex_a76ae = Cpu{
+ .name = "cortex_a76ae",
+ .llvm_name = "cortex-a76ae",
+ .features = featureSet(&[_]Feature{
+ .a76,
+ }),
+ };
+ pub const cyclone = Cpu{
+ .name = "cyclone",
+ .llvm_name = "cyclone",
+ .features = featureSet(&[_]Feature{
+ .cyclone,
+ }),
+ };
+ pub const exynos_m1 = Cpu{
+ .name = "exynos_m1",
+ .llvm_name = "exynos-m1",
+ .features = featureSet(&[_]Feature{
+ .exynosm1,
+ }),
+ };
+ pub const exynos_m2 = Cpu{
+ .name = "exynos_m2",
+ .llvm_name = "exynos-m2",
+ .features = featureSet(&[_]Feature{
+ .exynosm2,
+ }),
+ };
+ pub const exynos_m3 = Cpu{
+ .name = "exynos_m3",
+ .llvm_name = "exynos-m3",
+ .features = featureSet(&[_]Feature{
+ .exynosm3,
+ }),
+ };
+ pub const exynos_m4 = Cpu{
+ .name = "exynos_m4",
+ .llvm_name = "exynos-m4",
+ .features = featureSet(&[_]Feature{
+ .exynosm4,
+ }),
+ };
+ pub const exynos_m5 = Cpu{
+ .name = "exynos_m5",
+ .llvm_name = "exynos-m5",
+ .features = featureSet(&[_]Feature{
+ .exynosm4,
+ }),
+ };
+ pub const falkor = Cpu{
+ .name = "falkor",
+ .llvm_name = "falkor",
+ .features = featureSet(&[_]Feature{
+ .falkor,
+ }),
+ };
+ pub const generic = Cpu{
+ .name = "generic",
+ .llvm_name = "generic",
+ .features = featureSet(&[_]Feature{
+ .fp_armv8,
+ .fuse_aes,
+ .neon,
+ .perfmon,
+ .use_postra_scheduler,
+ }),
+ };
+ pub const kryo = Cpu{
+ .name = "kryo",
+ .llvm_name = "kryo",
+ .features = featureSet(&[_]Feature{
+ .kryo,
+ }),
+ };
+ pub const saphira = Cpu{
+ .name = "saphira",
+ .llvm_name = "saphira",
+ .features = featureSet(&[_]Feature{
+ .saphira,
+ }),
+ };
+ pub const thunderx = Cpu{
+ .name = "thunderx",
+ .llvm_name = "thunderx",
+ .features = featureSet(&[_]Feature{
+ .thunderx,
+ }),
+ };
+ pub const thunderx2t99 = Cpu{
+ .name = "thunderx2t99",
+ .llvm_name = "thunderx2t99",
+ .features = featureSet(&[_]Feature{
+ .thunderx2t99,
+ }),
+ };
+ pub const thunderxt81 = Cpu{
+ .name = "thunderxt81",
+ .llvm_name = "thunderxt81",
+ .features = featureSet(&[_]Feature{
+ .thunderxt81,
+ }),
+ };
+ pub const thunderxt83 = Cpu{
+ .name = "thunderxt83",
+ .llvm_name = "thunderxt83",
+ .features = featureSet(&[_]Feature{
+ .thunderxt83,
+ }),
+ };
+ pub const thunderxt88 = Cpu{
+ .name = "thunderxt88",
+ .llvm_name = "thunderxt88",
+ .features = featureSet(&[_]Feature{
+ .thunderxt88,
+ }),
+ };
+ pub const tsv110 = Cpu{
+ .name = "tsv110",
+ .llvm_name = "tsv110",
+ .features = featureSet(&[_]Feature{
+ .tsv110,
+ }),
+ };
+};
+
+/// All aarch64 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.apple_latest,
+ &cpu.cortex_a35,
+ &cpu.cortex_a53,
+ &cpu.cortex_a55,
+ &cpu.cortex_a57,
+ &cpu.cortex_a72,
+ &cpu.cortex_a73,
+ &cpu.cortex_a75,
+ &cpu.cortex_a76,
+ &cpu.cortex_a76ae,
+ &cpu.cyclone,
+ &cpu.exynos_m1,
+ &cpu.exynos_m2,
+ &cpu.exynos_m3,
+ &cpu.exynos_m4,
+ &cpu.exynos_m5,
+ &cpu.falkor,
+ &cpu.generic,
+ &cpu.kryo,
+ &cpu.saphira,
+ &cpu.thunderx,
+ &cpu.thunderx2t99,
+ &cpu.thunderxt81,
+ &cpu.thunderxt83,
+ &cpu.thunderxt88,
+ &cpu.tsv110,
+};
diff --git a/lib/std/target/amdgpu.zig b/lib/std/target/amdgpu.zig
new file mode 100644
index 0000000000..182b9fa453
--- /dev/null
+++ b/lib/std/target/amdgpu.zig
@@ -0,0 +1,1315 @@
+const std = @import("../std.zig");
+const Cpu = std.Target.Cpu;
+
+pub const Feature = enum {
+ @"16_bit_insts",
+ DumpCode,
+ add_no_carry_insts,
+ aperture_regs,
+ atomic_fadd_insts,
+ auto_waitcnt_before_barrier,
+ ci_insts,
+ code_object_v3,
+ cumode,
+ dl_insts,
+ dot1_insts,
+ dot2_insts,
+ dot3_insts,
+ dot4_insts,
+ dot5_insts,
+ dot6_insts,
+ dpp,
+ dpp8,
+ dumpcode,
+ enable_ds128,
+ enable_prt_strict_null,
+ fast_fmaf,
+ flat_address_space,
+ flat_for_global,
+ flat_global_insts,
+ flat_inst_offsets,
+ flat_scratch_insts,
+ flat_segment_offset_bug,
+ fma_mix_insts,
+ fmaf,
+ fp_exceptions,
+ fp16_denormals,
+ fp32_denormals,
+ fp64,
+ fp64_denormals,
+ fp64_fp16_denormals,
+ gcn3_encoding,
+ gfx10,
+ gfx10_insts,
+ gfx7_gfx8_gfx9_insts,
+ gfx8_insts,
+ gfx9,
+ gfx9_insts,
+ half_rate_64_ops,
+ inst_fwd_prefetch_bug,
+ int_clamp_insts,
+ inv_2pi_inline_imm,
+ lds_branch_vmem_war_hazard,
+ lds_misaligned_bug,
+ ldsbankcount16,
+ ldsbankcount32,
+ load_store_opt,
+ localmemorysize0,
+ localmemorysize32768,
+ localmemorysize65536,
+ mad_mix_insts,
+ mai_insts,
+ max_private_element_size_16,
+ max_private_element_size_4,
+ max_private_element_size_8,
+ mimg_r128,
+ movrel,
+ no_data_dep_hazard,
+ no_sdst_cmpx,
+ no_sram_ecc_support,
+ no_xnack_support,
+ nsa_encoding,
+ nsa_to_vmem_bug,
+ offset_3f_bug,
+ pk_fmac_f16_inst,
+ promote_alloca,
+ r128_a16,
+ register_banking,
+ s_memrealtime,
+ scalar_atomics,
+ scalar_flat_scratch_insts,
+ scalar_stores,
+ sdwa,
+ sdwa_mav,
+ sdwa_omod,
+ sdwa_out_mods_vopc,
+ sdwa_scalar,
+ sdwa_sdst,
+ sea_islands,
+ sgpr_init_bug,
+ si_scheduler,
+ smem_to_vector_write_hazard,
+ southern_islands,
+ sram_ecc,
+ trap_handler,
+ trig_reduced_range,
+ unaligned_buffer_access,
+ unaligned_scratch_access,
+ unpacked_d16_vmem,
+ unsafe_ds_offset_folding,
+ vcmpx_exec_war_hazard,
+ vcmpx_permlane_hazard,
+ vgpr_index_mode,
+ vmem_to_scalar_write_hazard,
+ volcanic_islands,
+ vop3_literal,
+ vop3p,
+ vscnt,
+ wavefrontsize16,
+ wavefrontsize32,
+ wavefrontsize64,
+ xnack,
+};
+
+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.@"16_bit_insts")] = .{
+ .llvm_name = "16-bit-insts",
+ .description = "Has i16/f16 instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.DumpCode)] = .{
+ .llvm_name = "DumpCode",
+ .description = "Dump MachineInstrs in the CodeEmitter",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.add_no_carry_insts)] = .{
+ .llvm_name = "add-no-carry-insts",
+ .description = "Have VALU add/sub instructions without carry out",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.aperture_regs)] = .{
+ .llvm_name = "aperture-regs",
+ .description = "Has Memory Aperture Base and Size Registers",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.atomic_fadd_insts)] = .{
+ .llvm_name = "atomic-fadd-insts",
+ .description = "Has buffer_atomic_add_f32, buffer_atomic_pk_add_f16, global_atomic_add_f32, global_atomic_pk_add_f16 instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.auto_waitcnt_before_barrier)] = .{
+ .llvm_name = "auto-waitcnt-before-barrier",
+ .description = "Hardware automatically inserts waitcnt before barrier",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ci_insts)] = .{
+ .llvm_name = "ci-insts",
+ .description = "Additional instructions for CI+",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.code_object_v3)] = .{
+ .llvm_name = "code-object-v3",
+ .description = "Generate code object version 3",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.cumode)] = .{
+ .llvm_name = "cumode",
+ .description = "Enable CU wavefront execution mode",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dl_insts)] = .{
+ .llvm_name = "dl-insts",
+ .description = "Has v_fmac_f32 and v_xnor_b32 instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dot1_insts)] = .{
+ .llvm_name = "dot1-insts",
+ .description = "Has v_dot4_i32_i8 and v_dot8_i32_i4 instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dot2_insts)] = .{
+ .llvm_name = "dot2-insts",
+ .description = "Has v_dot2_f32_f16, v_dot2_i32_i16, v_dot2_u32_u16, v_dot4_u32_u8, v_dot8_u32_u4 instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dot3_insts)] = .{
+ .llvm_name = "dot3-insts",
+ .description = "Has v_dot8c_i32_i4 instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dot4_insts)] = .{
+ .llvm_name = "dot4-insts",
+ .description = "Has v_dot2c_i32_i16 instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dot5_insts)] = .{
+ .llvm_name = "dot5-insts",
+ .description = "Has v_dot2c_f32_f16 instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dot6_insts)] = .{
+ .llvm_name = "dot6-insts",
+ .description = "Has v_dot4c_i32_i8 instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dpp)] = .{
+ .llvm_name = "dpp",
+ .description = "Support DPP (Data Parallel Primitives) extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dpp8)] = .{
+ .llvm_name = "dpp8",
+ .description = "Support DPP8 (Data Parallel Primitives) extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dumpcode)] = .{
+ .llvm_name = "dumpcode",
+ .description = "Dump MachineInstrs in the CodeEmitter",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.enable_ds128)] = .{
+ .llvm_name = "enable-ds128",
+ .description = "Use ds_read|write_b128",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.enable_prt_strict_null)] = .{
+ .llvm_name = "enable-prt-strict-null",
+ .description = "Enable zeroing of result registers for sparse texture fetches",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_fmaf)] = .{
+ .llvm_name = "fast-fmaf",
+ .description = "Assuming f32 fma is at least as fast as mul + add",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.flat_address_space)] = .{
+ .llvm_name = "flat-address-space",
+ .description = "Support flat address space",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.flat_for_global)] = .{
+ .llvm_name = "flat-for-global",
+ .description = "Force to generate flat instruction for global",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.flat_global_insts)] = .{
+ .llvm_name = "flat-global-insts",
+ .description = "Have global_* flat memory instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.flat_inst_offsets)] = .{
+ .llvm_name = "flat-inst-offsets",
+ .description = "Flat instructions have immediate offset addressing mode",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.flat_scratch_insts)] = .{
+ .llvm_name = "flat-scratch-insts",
+ .description = "Have scratch_* flat memory instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.flat_segment_offset_bug)] = .{
+ .llvm_name = "flat-segment-offset-bug",
+ .description = "GFX10 bug, inst_offset ignored in flat segment",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fma_mix_insts)] = .{
+ .llvm_name = "fma-mix-insts",
+ .description = "Has v_fma_mix_f32, v_fma_mixlo_f16, v_fma_mixhi_f16 instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fmaf)] = .{
+ .llvm_name = "fmaf",
+ .description = "Enable single precision FMA (not as fast as mul+add, but fused)",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fp_exceptions)] = .{
+ .llvm_name = "fp-exceptions",
+ .description = "Enable floating point exceptions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fp16_denormals)] = .{
+ .llvm_name = "fp16-denormals",
+ .description = "Enable half precision denormal handling",
+ .dependencies = featureSet(&[_]Feature{
+ .fp64_fp16_denormals,
+ }),
+ };
+ result[@enumToInt(Feature.fp32_denormals)] = .{
+ .llvm_name = "fp32-denormals",
+ .description = "Enable single precision denormal handling",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fp64)] = .{
+ .llvm_name = "fp64",
+ .description = "Enable double precision operations",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fp64_denormals)] = .{
+ .llvm_name = "fp64-denormals",
+ .description = "Enable double and half precision denormal handling",
+ .dependencies = featureSet(&[_]Feature{
+ .fp64,
+ .fp64_fp16_denormals,
+ }),
+ };
+ result[@enumToInt(Feature.fp64_fp16_denormals)] = .{
+ .llvm_name = "fp64-fp16-denormals",
+ .description = "Enable double and half precision denormal handling",
+ .dependencies = featureSet(&[_]Feature{
+ .fp64,
+ }),
+ };
+ result[@enumToInt(Feature.gcn3_encoding)] = .{
+ .llvm_name = "gcn3-encoding",
+ .description = "Encoding format for VI",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.gfx10)] = .{
+ .llvm_name = "gfx10",
+ .description = "GFX10 GPU generation",
+ .dependencies = featureSet(&[_]Feature{
+ .@"16_bit_insts",
+ .add_no_carry_insts,
+ .aperture_regs,
+ .ci_insts,
+ .dpp,
+ .dpp8,
+ .fast_fmaf,
+ .flat_address_space,
+ .flat_global_insts,
+ .flat_inst_offsets,
+ .flat_scratch_insts,
+ .fma_mix_insts,
+ .fp64,
+ .gfx10_insts,
+ .gfx8_insts,
+ .gfx9_insts,
+ .int_clamp_insts,
+ .inv_2pi_inline_imm,
+ .localmemorysize65536,
+ .mimg_r128,
+ .movrel,
+ .no_data_dep_hazard,
+ .no_sdst_cmpx,
+ .no_sram_ecc_support,
+ .pk_fmac_f16_inst,
+ .register_banking,
+ .s_memrealtime,
+ .sdwa,
+ .sdwa_omod,
+ .sdwa_scalar,
+ .sdwa_sdst,
+ .vop3_literal,
+ .vop3p,
+ .vscnt,
+ }),
+ };
+ result[@enumToInt(Feature.gfx10_insts)] = .{
+ .llvm_name = "gfx10-insts",
+ .description = "Additional instructions for GFX10+",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.gfx7_gfx8_gfx9_insts)] = .{
+ .llvm_name = "gfx7-gfx8-gfx9-insts",
+ .description = "Instructions shared in GFX7, GFX8, GFX9",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.gfx8_insts)] = .{
+ .llvm_name = "gfx8-insts",
+ .description = "Additional instructions for GFX8+",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.gfx9)] = .{
+ .llvm_name = "gfx9",
+ .description = "GFX9 GPU generation",
+ .dependencies = featureSet(&[_]Feature{
+ .@"16_bit_insts",
+ .add_no_carry_insts,
+ .aperture_regs,
+ .ci_insts,
+ .dpp,
+ .fast_fmaf,
+ .flat_address_space,
+ .flat_global_insts,
+ .flat_inst_offsets,
+ .flat_scratch_insts,
+ .fp64,
+ .gcn3_encoding,
+ .gfx7_gfx8_gfx9_insts,
+ .gfx8_insts,
+ .gfx9_insts,
+ .int_clamp_insts,
+ .inv_2pi_inline_imm,
+ .localmemorysize65536,
+ .r128_a16,
+ .s_memrealtime,
+ .scalar_atomics,
+ .scalar_flat_scratch_insts,
+ .scalar_stores,
+ .sdwa,
+ .sdwa_omod,
+ .sdwa_scalar,
+ .sdwa_sdst,
+ .vgpr_index_mode,
+ .vop3p,
+ .wavefrontsize64,
+ }),
+ };
+ result[@enumToInt(Feature.gfx9_insts)] = .{
+ .llvm_name = "gfx9-insts",
+ .description = "Additional instructions for GFX9+",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.half_rate_64_ops)] = .{
+ .llvm_name = "half-rate-64-ops",
+ .description = "Most fp64 instructions are half rate instead of quarter",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.inst_fwd_prefetch_bug)] = .{
+ .llvm_name = "inst-fwd-prefetch-bug",
+ .description = "S_INST_PREFETCH instruction causes shader to hang",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.int_clamp_insts)] = .{
+ .llvm_name = "int-clamp-insts",
+ .description = "Support clamp for integer destination",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.inv_2pi_inline_imm)] = .{
+ .llvm_name = "inv-2pi-inline-imm",
+ .description = "Has 1 / (2 * pi) as inline immediate",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.lds_branch_vmem_war_hazard)] = .{
+ .llvm_name = "lds-branch-vmem-war-hazard",
+ .description = "Switching between LDS and VMEM-tex not waiting VM_VSRC=0",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.lds_misaligned_bug)] = .{
+ .llvm_name = "lds-misaligned-bug",
+ .description = "Some GFX10 bug with misaligned multi-dword LDS access in WGP mode",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ldsbankcount16)] = .{
+ .llvm_name = "ldsbankcount16",
+ .description = "The number of LDS banks per compute unit.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ldsbankcount32)] = .{
+ .llvm_name = "ldsbankcount32",
+ .description = "The number of LDS banks per compute unit.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.load_store_opt)] = .{
+ .llvm_name = "load-store-opt",
+ .description = "Enable SI load/store optimizer pass",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.localmemorysize0)] = .{
+ .llvm_name = "localmemorysize0",
+ .description = "The size of local memory in bytes",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.localmemorysize32768)] = .{
+ .llvm_name = "localmemorysize32768",
+ .description = "The size of local memory in bytes",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.localmemorysize65536)] = .{
+ .llvm_name = "localmemorysize65536",
+ .description = "The size of local memory in bytes",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.mad_mix_insts)] = .{
+ .llvm_name = "mad-mix-insts",
+ .description = "Has v_mad_mix_f32, v_mad_mixlo_f16, v_mad_mixhi_f16 instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.mai_insts)] = .{
+ .llvm_name = "mai-insts",
+ .description = "Has mAI instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.max_private_element_size_16)] = .{
+ .llvm_name = "max-private-element-size-16",
+ .description = "Maximum private access size may be 16",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.max_private_element_size_4)] = .{
+ .llvm_name = "max-private-element-size-4",
+ .description = "Maximum private access size may be 4",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.max_private_element_size_8)] = .{
+ .llvm_name = "max-private-element-size-8",
+ .description = "Maximum private access size may be 8",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.mimg_r128)] = .{
+ .llvm_name = "mimg-r128",
+ .description = "Support 128-bit texture resources",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.movrel)] = .{
+ .llvm_name = "movrel",
+ .description = "Has v_movrel*_b32 instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.no_data_dep_hazard)] = .{
+ .llvm_name = "no-data-dep-hazard",
+ .description = "Does not need SW waitstates",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.no_sdst_cmpx)] = .{
+ .llvm_name = "no-sdst-cmpx",
+ .description = "V_CMPX does not write VCC/SGPR in addition to EXEC",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.no_sram_ecc_support)] = .{
+ .llvm_name = "no-sram-ecc-support",
+ .description = "Hardware does not support SRAM ECC",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.no_xnack_support)] = .{
+ .llvm_name = "no-xnack-support",
+ .description = "Hardware does not support XNACK",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.nsa_encoding)] = .{
+ .llvm_name = "nsa-encoding",
+ .description = "Support NSA encoding for image instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.nsa_to_vmem_bug)] = .{
+ .llvm_name = "nsa-to-vmem-bug",
+ .description = "MIMG-NSA followed by VMEM fail if EXEC_LO or EXEC_HI equals zero",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.offset_3f_bug)] = .{
+ .llvm_name = "offset-3f-bug",
+ .description = "Branch offset of 3f hardware bug",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.pk_fmac_f16_inst)] = .{
+ .llvm_name = "pk-fmac-f16-inst",
+ .description = "Has v_pk_fmac_f16 instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.promote_alloca)] = .{
+ .llvm_name = "promote-alloca",
+ .description = "Enable promote alloca pass",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.r128_a16)] = .{
+ .llvm_name = "r128-a16",
+ .description = "Support 16 bit coordindates/gradients/lod/clamp/mip types on gfx9",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.register_banking)] = .{
+ .llvm_name = "register-banking",
+ .description = "Has register banking",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.s_memrealtime)] = .{
+ .llvm_name = "s-memrealtime",
+ .description = "Has s_memrealtime instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.scalar_atomics)] = .{
+ .llvm_name = "scalar-atomics",
+ .description = "Has atomic scalar memory instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.scalar_flat_scratch_insts)] = .{
+ .llvm_name = "scalar-flat-scratch-insts",
+ .description = "Have s_scratch_* flat memory instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.scalar_stores)] = .{
+ .llvm_name = "scalar-stores",
+ .description = "Has store scalar memory instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sdwa)] = .{
+ .llvm_name = "sdwa",
+ .description = "Support SDWA (Sub-DWORD Addressing) extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sdwa_mav)] = .{
+ .llvm_name = "sdwa-mav",
+ .description = "Support v_mac_f32/f16 with SDWA (Sub-DWORD Addressing) extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sdwa_omod)] = .{
+ .llvm_name = "sdwa-omod",
+ .description = "Support OMod with SDWA (Sub-DWORD Addressing) extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sdwa_out_mods_vopc)] = .{
+ .llvm_name = "sdwa-out-mods-vopc",
+ .description = "Support clamp for VOPC with SDWA (Sub-DWORD Addressing) extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sdwa_scalar)] = .{
+ .llvm_name = "sdwa-scalar",
+ .description = "Support scalar register with SDWA (Sub-DWORD Addressing) extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sdwa_sdst)] = .{
+ .llvm_name = "sdwa-sdst",
+ .description = "Support scalar dst for VOPC with SDWA (Sub-DWORD Addressing) extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sea_islands)] = .{
+ .llvm_name = "sea-islands",
+ .description = "SEA_ISLANDS GPU generation",
+ .dependencies = featureSet(&[_]Feature{
+ .ci_insts,
+ .flat_address_space,
+ .fp64,
+ .gfx7_gfx8_gfx9_insts,
+ .localmemorysize65536,
+ .mimg_r128,
+ .movrel,
+ .no_sram_ecc_support,
+ .trig_reduced_range,
+ .wavefrontsize64,
+ }),
+ };
+ result[@enumToInt(Feature.sgpr_init_bug)] = .{
+ .llvm_name = "sgpr-init-bug",
+ .description = "VI SGPR initialization bug requiring a fixed SGPR allocation size",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.si_scheduler)] = .{
+ .llvm_name = "si-scheduler",
+ .description = "Enable SI Machine Scheduler",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.smem_to_vector_write_hazard)] = .{
+ .llvm_name = "smem-to-vector-write-hazard",
+ .description = "s_load_dword followed by v_cmp page faults",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.southern_islands)] = .{
+ .llvm_name = "southern-islands",
+ .description = "SOUTHERN_ISLANDS GPU generation",
+ .dependencies = featureSet(&[_]Feature{
+ .fp64,
+ .ldsbankcount32,
+ .localmemorysize32768,
+ .mimg_r128,
+ .movrel,
+ .no_sram_ecc_support,
+ .no_xnack_support,
+ .trig_reduced_range,
+ .wavefrontsize64,
+ }),
+ };
+ result[@enumToInt(Feature.sram_ecc)] = .{
+ .llvm_name = "sram-ecc",
+ .description = "Enable SRAM ECC",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.trap_handler)] = .{
+ .llvm_name = "trap-handler",
+ .description = "Trap handler support",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.trig_reduced_range)] = .{
+ .llvm_name = "trig-reduced-range",
+ .description = "Requires use of fract on arguments to trig instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.unaligned_buffer_access)] = .{
+ .llvm_name = "unaligned-buffer-access",
+ .description = "Support unaligned global loads and stores",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.unaligned_scratch_access)] = .{
+ .llvm_name = "unaligned-scratch-access",
+ .description = "Support unaligned scratch loads and stores",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.unpacked_d16_vmem)] = .{
+ .llvm_name = "unpacked-d16-vmem",
+ .description = "Has unpacked d16 vmem instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.unsafe_ds_offset_folding)] = .{
+ .llvm_name = "unsafe-ds-offset-folding",
+ .description = "Force using DS instruction immediate offsets on SI",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.vcmpx_exec_war_hazard)] = .{
+ .llvm_name = "vcmpx-exec-war-hazard",
+ .description = "V_CMPX WAR hazard on EXEC (V_CMPX issue ONLY)",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.vcmpx_permlane_hazard)] = .{
+ .llvm_name = "vcmpx-permlane-hazard",
+ .description = "TODO: describe me",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.vgpr_index_mode)] = .{
+ .llvm_name = "vgpr-index-mode",
+ .description = "Has VGPR mode register indexing",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.vmem_to_scalar_write_hazard)] = .{
+ .llvm_name = "vmem-to-scalar-write-hazard",
+ .description = "VMEM instruction followed by scalar writing to EXEC mask, M0 or SGPR leads to incorrect execution.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.volcanic_islands)] = .{
+ .llvm_name = "volcanic-islands",
+ .description = "VOLCANIC_ISLANDS GPU generation",
+ .dependencies = featureSet(&[_]Feature{
+ .@"16_bit_insts",
+ .ci_insts,
+ .dpp,
+ .flat_address_space,
+ .fp64,
+ .gcn3_encoding,
+ .gfx7_gfx8_gfx9_insts,
+ .gfx8_insts,
+ .int_clamp_insts,
+ .inv_2pi_inline_imm,
+ .localmemorysize65536,
+ .mimg_r128,
+ .movrel,
+ .no_sram_ecc_support,
+ .s_memrealtime,
+ .scalar_stores,
+ .sdwa,
+ .sdwa_mav,
+ .sdwa_out_mods_vopc,
+ .trig_reduced_range,
+ .vgpr_index_mode,
+ .wavefrontsize64,
+ }),
+ };
+ result[@enumToInt(Feature.vop3_literal)] = .{
+ .llvm_name = "vop3-literal",
+ .description = "Can use one literal in VOP3",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.vop3p)] = .{
+ .llvm_name = "vop3p",
+ .description = "Has VOP3P packed instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.vscnt)] = .{
+ .llvm_name = "vscnt",
+ .description = "Has separate store vscnt counter",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.wavefrontsize16)] = .{
+ .llvm_name = "wavefrontsize16",
+ .description = "The number of threads per wavefront",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.wavefrontsize32)] = .{
+ .llvm_name = "wavefrontsize32",
+ .description = "The number of threads per wavefront",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.wavefrontsize64)] = .{
+ .llvm_name = "wavefrontsize64",
+ .description = "The number of threads per wavefront",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.xnack)] = .{
+ .llvm_name = "xnack",
+ .description = "Enable XNACK support",
+ .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 bonaire = Cpu{
+ .name = "bonaire",
+ .llvm_name = "bonaire",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .sea_islands,
+ }),
+ };
+ pub const carrizo = Cpu{
+ .name = "carrizo",
+ .llvm_name = "carrizo",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .fast_fmaf,
+ .half_rate_64_ops,
+ .ldsbankcount32,
+ .unpacked_d16_vmem,
+ .volcanic_islands,
+ .xnack,
+ }),
+ };
+ pub const fiji = Cpu{
+ .name = "fiji",
+ .llvm_name = "fiji",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .unpacked_d16_vmem,
+ .volcanic_islands,
+ }),
+ };
+ pub const generic = Cpu{
+ .name = "generic",
+ .llvm_name = "generic",
+ .features = featureSet(&[_]Feature{
+ .wavefrontsize64,
+ }),
+ };
+ pub const generic_hsa = Cpu{
+ .name = "generic_hsa",
+ .llvm_name = "generic-hsa",
+ .features = featureSet(&[_]Feature{
+ .flat_address_space,
+ .wavefrontsize64,
+ }),
+ };
+ pub const gfx1010 = Cpu{
+ .name = "gfx1010",
+ .llvm_name = "gfx1010",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .dl_insts,
+ .flat_segment_offset_bug,
+ .gfx10,
+ .inst_fwd_prefetch_bug,
+ .lds_branch_vmem_war_hazard,
+ .lds_misaligned_bug,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .nsa_encoding,
+ .nsa_to_vmem_bug,
+ .offset_3f_bug,
+ .scalar_atomics,
+ .scalar_flat_scratch_insts,
+ .scalar_stores,
+ .smem_to_vector_write_hazard,
+ .vcmpx_exec_war_hazard,
+ .vcmpx_permlane_hazard,
+ .vmem_to_scalar_write_hazard,
+ .wavefrontsize32,
+ }),
+ };
+ pub const gfx1011 = Cpu{
+ .name = "gfx1011",
+ .llvm_name = "gfx1011",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .dl_insts,
+ .dot1_insts,
+ .dot2_insts,
+ .dot5_insts,
+ .dot6_insts,
+ .flat_segment_offset_bug,
+ .gfx10,
+ .inst_fwd_prefetch_bug,
+ .lds_branch_vmem_war_hazard,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .nsa_encoding,
+ .nsa_to_vmem_bug,
+ .offset_3f_bug,
+ .scalar_atomics,
+ .scalar_flat_scratch_insts,
+ .scalar_stores,
+ .smem_to_vector_write_hazard,
+ .vcmpx_exec_war_hazard,
+ .vcmpx_permlane_hazard,
+ .vmem_to_scalar_write_hazard,
+ .wavefrontsize32,
+ }),
+ };
+ pub const gfx1012 = Cpu{
+ .name = "gfx1012",
+ .llvm_name = "gfx1012",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .dl_insts,
+ .dot1_insts,
+ .dot2_insts,
+ .dot5_insts,
+ .dot6_insts,
+ .flat_segment_offset_bug,
+ .gfx10,
+ .inst_fwd_prefetch_bug,
+ .lds_branch_vmem_war_hazard,
+ .lds_misaligned_bug,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .nsa_encoding,
+ .nsa_to_vmem_bug,
+ .offset_3f_bug,
+ .scalar_atomics,
+ .scalar_flat_scratch_insts,
+ .scalar_stores,
+ .smem_to_vector_write_hazard,
+ .vcmpx_exec_war_hazard,
+ .vcmpx_permlane_hazard,
+ .vmem_to_scalar_write_hazard,
+ .wavefrontsize32,
+ }),
+ };
+ pub const gfx600 = Cpu{
+ .name = "gfx600",
+ .llvm_name = "gfx600",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .fast_fmaf,
+ .half_rate_64_ops,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .southern_islands,
+ }),
+ };
+ pub const gfx601 = Cpu{
+ .name = "gfx601",
+ .llvm_name = "gfx601",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .southern_islands,
+ }),
+ };
+ pub const gfx700 = Cpu{
+ .name = "gfx700",
+ .llvm_name = "gfx700",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .sea_islands,
+ }),
+ };
+ pub const gfx701 = Cpu{
+ .name = "gfx701",
+ .llvm_name = "gfx701",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .fast_fmaf,
+ .half_rate_64_ops,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .sea_islands,
+ }),
+ };
+ pub const gfx702 = Cpu{
+ .name = "gfx702",
+ .llvm_name = "gfx702",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .fast_fmaf,
+ .ldsbankcount16,
+ .no_xnack_support,
+ .sea_islands,
+ }),
+ };
+ pub const gfx703 = Cpu{
+ .name = "gfx703",
+ .llvm_name = "gfx703",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount16,
+ .no_xnack_support,
+ .sea_islands,
+ }),
+ };
+ pub const gfx704 = Cpu{
+ .name = "gfx704",
+ .llvm_name = "gfx704",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .sea_islands,
+ }),
+ };
+ pub const gfx801 = Cpu{
+ .name = "gfx801",
+ .llvm_name = "gfx801",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .fast_fmaf,
+ .half_rate_64_ops,
+ .ldsbankcount32,
+ .unpacked_d16_vmem,
+ .volcanic_islands,
+ .xnack,
+ }),
+ };
+ pub const gfx802 = Cpu{
+ .name = "gfx802",
+ .llvm_name = "gfx802",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .sgpr_init_bug,
+ .unpacked_d16_vmem,
+ .volcanic_islands,
+ }),
+ };
+ pub const gfx803 = Cpu{
+ .name = "gfx803",
+ .llvm_name = "gfx803",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .unpacked_d16_vmem,
+ .volcanic_islands,
+ }),
+ };
+ pub const gfx810 = Cpu{
+ .name = "gfx810",
+ .llvm_name = "gfx810",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount16,
+ .volcanic_islands,
+ .xnack,
+ }),
+ };
+ pub const gfx900 = Cpu{
+ .name = "gfx900",
+ .llvm_name = "gfx900",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .gfx9,
+ .ldsbankcount32,
+ .mad_mix_insts,
+ .no_sram_ecc_support,
+ .no_xnack_support,
+ }),
+ };
+ pub const gfx902 = Cpu{
+ .name = "gfx902",
+ .llvm_name = "gfx902",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .gfx9,
+ .ldsbankcount32,
+ .mad_mix_insts,
+ .no_sram_ecc_support,
+ .xnack,
+ }),
+ };
+ pub const gfx904 = Cpu{
+ .name = "gfx904",
+ .llvm_name = "gfx904",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .fma_mix_insts,
+ .gfx9,
+ .ldsbankcount32,
+ .no_sram_ecc_support,
+ .no_xnack_support,
+ }),
+ };
+ pub const gfx906 = Cpu{
+ .name = "gfx906",
+ .llvm_name = "gfx906",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .dl_insts,
+ .dot1_insts,
+ .dot2_insts,
+ .fma_mix_insts,
+ .gfx9,
+ .half_rate_64_ops,
+ .ldsbankcount32,
+ .no_xnack_support,
+ }),
+ };
+ pub const gfx908 = Cpu{
+ .name = "gfx908",
+ .llvm_name = "gfx908",
+ .features = featureSet(&[_]Feature{
+ .atomic_fadd_insts,
+ .code_object_v3,
+ .dl_insts,
+ .dot1_insts,
+ .dot2_insts,
+ .dot3_insts,
+ .dot4_insts,
+ .dot5_insts,
+ .dot6_insts,
+ .fma_mix_insts,
+ .gfx9,
+ .half_rate_64_ops,
+ .ldsbankcount32,
+ .mai_insts,
+ .pk_fmac_f16_inst,
+ .sram_ecc,
+ }),
+ };
+ pub const gfx909 = Cpu{
+ .name = "gfx909",
+ .llvm_name = "gfx909",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .gfx9,
+ .ldsbankcount32,
+ .mad_mix_insts,
+ .xnack,
+ }),
+ };
+ pub const hainan = Cpu{
+ .name = "hainan",
+ .llvm_name = "hainan",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .southern_islands,
+ }),
+ };
+ pub const hawaii = Cpu{
+ .name = "hawaii",
+ .llvm_name = "hawaii",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .fast_fmaf,
+ .half_rate_64_ops,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .sea_islands,
+ }),
+ };
+ pub const iceland = Cpu{
+ .name = "iceland",
+ .llvm_name = "iceland",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .sgpr_init_bug,
+ .unpacked_d16_vmem,
+ .volcanic_islands,
+ }),
+ };
+ pub const kabini = Cpu{
+ .name = "kabini",
+ .llvm_name = "kabini",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount16,
+ .no_xnack_support,
+ .sea_islands,
+ }),
+ };
+ pub const kaveri = Cpu{
+ .name = "kaveri",
+ .llvm_name = "kaveri",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .sea_islands,
+ }),
+ };
+ pub const mullins = Cpu{
+ .name = "mullins",
+ .llvm_name = "mullins",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount16,
+ .no_xnack_support,
+ .sea_islands,
+ }),
+ };
+ pub const oland = Cpu{
+ .name = "oland",
+ .llvm_name = "oland",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .southern_islands,
+ }),
+ };
+ pub const pitcairn = Cpu{
+ .name = "pitcairn",
+ .llvm_name = "pitcairn",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .southern_islands,
+ }),
+ };
+ pub const polaris10 = Cpu{
+ .name = "polaris10",
+ .llvm_name = "polaris10",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .unpacked_d16_vmem,
+ .volcanic_islands,
+ }),
+ };
+ pub const polaris11 = Cpu{
+ .name = "polaris11",
+ .llvm_name = "polaris11",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .unpacked_d16_vmem,
+ .volcanic_islands,
+ }),
+ };
+ pub const stoney = Cpu{
+ .name = "stoney",
+ .llvm_name = "stoney",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount16,
+ .volcanic_islands,
+ .xnack,
+ }),
+ };
+ pub const tahiti = Cpu{
+ .name = "tahiti",
+ .llvm_name = "tahiti",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .fast_fmaf,
+ .half_rate_64_ops,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .southern_islands,
+ }),
+ };
+ pub const tonga = Cpu{
+ .name = "tonga",
+ .llvm_name = "tonga",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .sgpr_init_bug,
+ .unpacked_d16_vmem,
+ .volcanic_islands,
+ }),
+ };
+ pub const verde = Cpu{
+ .name = "verde",
+ .llvm_name = "verde",
+ .features = featureSet(&[_]Feature{
+ .code_object_v3,
+ .ldsbankcount32,
+ .no_xnack_support,
+ .southern_islands,
+ }),
+ };
+};
+
+/// All amdgpu 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.bonaire,
+ &cpu.carrizo,
+ &cpu.fiji,
+ &cpu.generic,
+ &cpu.generic_hsa,
+ &cpu.gfx1010,
+ &cpu.gfx1011,
+ &cpu.gfx1012,
+ &cpu.gfx600,
+ &cpu.gfx601,
+ &cpu.gfx700,
+ &cpu.gfx701,
+ &cpu.gfx702,
+ &cpu.gfx703,
+ &cpu.gfx704,
+ &cpu.gfx801,
+ &cpu.gfx802,
+ &cpu.gfx803,
+ &cpu.gfx810,
+ &cpu.gfx900,
+ &cpu.gfx902,
+ &cpu.gfx904,
+ &cpu.gfx906,
+ &cpu.gfx908,
+ &cpu.gfx909,
+ &cpu.hainan,
+ &cpu.hawaii,
+ &cpu.iceland,
+ &cpu.kabini,
+ &cpu.kaveri,
+ &cpu.mullins,
+ &cpu.oland,
+ &cpu.pitcairn,
+ &cpu.polaris10,
+ &cpu.polaris11,
+ &cpu.stoney,
+ &cpu.tahiti,
+ &cpu.tonga,
+ &cpu.verde,
+};
diff --git a/lib/std/target/arm.zig b/lib/std/target/arm.zig
new file mode 100644
index 0000000000..62a4e1e835
--- /dev/null
+++ b/lib/std/target/arm.zig
@@ -0,0 +1,2333 @@
+const std = @import("../std.zig");
+const Cpu = std.Target.Cpu;
+
+pub const Feature = enum {
+ @"32bit",
+ @"8msecext",
+ a12,
+ a15,
+ a17,
+ a32,
+ a35,
+ a5,
+ a53,
+ a55,
+ a57,
+ a7,
+ a72,
+ a73,
+ a75,
+ a76,
+ a8,
+ a9,
+ aclass,
+ acquire_release,
+ aes,
+ armv2,
+ armv2a,
+ armv3,
+ armv3m,
+ armv4,
+ armv4t,
+ armv5t,
+ armv5te,
+ armv5tej,
+ armv6,
+ armv6_m,
+ armv6j,
+ armv6k,
+ armv6kz,
+ armv6s_m,
+ armv6t2,
+ armv7_a,
+ armv7_m,
+ armv7_r,
+ armv7e_m,
+ armv7k,
+ armv7s,
+ armv7ve,
+ armv8_a,
+ armv8_m_base,
+ armv8_m_main,
+ armv8_r,
+ armv8_1_a,
+ armv8_1_m_main,
+ armv8_2_a,
+ armv8_3_a,
+ armv8_4_a,
+ armv8_5_a,
+ avoid_movs_shop,
+ avoid_partial_cpsr,
+ cheap_predicable_cpsr,
+ crc,
+ crypto,
+ d32,
+ db,
+ dfb,
+ disable_postra_scheduler,
+ dont_widen_vmovs,
+ dotprod,
+ dsp,
+ execute_only,
+ expand_fp_mlx,
+ exynos,
+ fp_armv8,
+ fp_armv8d16,
+ fp_armv8d16sp,
+ fp_armv8sp,
+ fp16,
+ fp16fml,
+ fp64,
+ fpao,
+ fpregs,
+ fpregs16,
+ fpregs64,
+ fullfp16,
+ fuse_aes,
+ fuse_literals,
+ hwdiv,
+ hwdiv_arm,
+ iwmmxt,
+ iwmmxt2,
+ krait,
+ kryo,
+ lob,
+ long_calls,
+ loop_align,
+ m3,
+ mclass,
+ mp,
+ muxed_units,
+ mve,
+ mve_fp,
+ nacl_trap,
+ neon,
+ neon_fpmovs,
+ neonfp,
+ no_branch_predictor,
+ no_movt,
+ no_neg_immediates,
+ noarm,
+ nonpipelined_vfp,
+ perfmon,
+ prefer_ishst,
+ prefer_vmovsr,
+ prof_unpr,
+ r4,
+ r5,
+ r52,
+ r7,
+ ras,
+ rclass,
+ read_tp_hard,
+ reserve_r9,
+ ret_addr_stack,
+ sb,
+ sha2,
+ slow_fp_brcc,
+ slow_load_D_subreg,
+ slow_odd_reg,
+ slow_vdup32,
+ slow_vgetlni32,
+ slowfpvmlx,
+ soft_float,
+ splat_vfp_neon,
+ strict_align,
+ swift,
+ thumb_mode,
+ thumb2,
+ trustzone,
+ use_aa,
+ use_misched,
+ v4t,
+ v5t,
+ v5te,
+ v6,
+ v6k,
+ v6m,
+ v6t2,
+ v7,
+ v7clrex,
+ v8,
+ v8_1a,
+ v8_1m_main,
+ v8_2a,
+ v8_3a,
+ v8_4a,
+ v8_5a,
+ v8m,
+ v8m_main,
+ vfp2,
+ vfp2d16,
+ vfp2d16sp,
+ vfp2sp,
+ vfp3,
+ vfp3d16,
+ vfp3d16sp,
+ vfp3sp,
+ vfp4,
+ vfp4d16,
+ vfp4d16sp,
+ vfp4sp,
+ virtualization,
+ vldn_align,
+ vmlx_forwarding,
+ vmlx_hazards,
+ wide_stride_vfp,
+ xscale,
+ zcz,
+};
+
+pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
+
+pub const all_features = blk: {
+ @setEvalBranchQuota(10000);
+ 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.@"32bit")] = .{
+ .llvm_name = "32bit",
+ .description = "Prefer 32-bit Thumb instrs",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.@"8msecext")] = .{
+ .llvm_name = "8msecext",
+ .description = "Enable support for ARMv8-M Security Extensions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a12)] = .{
+ .llvm_name = "a12",
+ .description = "Cortex-A12 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a15)] = .{
+ .llvm_name = "a15",
+ .description = "Cortex-A15 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a17)] = .{
+ .llvm_name = "a17",
+ .description = "Cortex-A17 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a32)] = .{
+ .llvm_name = "a32",
+ .description = "Cortex-A32 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a35)] = .{
+ .llvm_name = "a35",
+ .description = "Cortex-A35 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a5)] = .{
+ .llvm_name = "a5",
+ .description = "Cortex-A5 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a53)] = .{
+ .llvm_name = "a53",
+ .description = "Cortex-A53 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a55)] = .{
+ .llvm_name = "a55",
+ .description = "Cortex-A55 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a57)] = .{
+ .llvm_name = "a57",
+ .description = "Cortex-A57 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a7)] = .{
+ .llvm_name = "a7",
+ .description = "Cortex-A7 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a72)] = .{
+ .llvm_name = "a72",
+ .description = "Cortex-A72 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a73)] = .{
+ .llvm_name = "a73",
+ .description = "Cortex-A73 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a75)] = .{
+ .llvm_name = "a75",
+ .description = "Cortex-A75 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a76)] = .{
+ .llvm_name = "a76",
+ .description = "Cortex-A76 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a8)] = .{
+ .llvm_name = "a8",
+ .description = "Cortex-A8 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.a9)] = .{
+ .llvm_name = "a9",
+ .description = "Cortex-A9 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.aclass)] = .{
+ .llvm_name = "aclass",
+ .description = "Is application profile ('A' series)",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.acquire_release)] = .{
+ .llvm_name = "acquire-release",
+ .description = "Has v8 acquire/release (lda/ldaex etc) instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.aes)] = .{
+ .llvm_name = "aes",
+ .description = "Enable AES support",
+ .dependencies = featureSet(&[_]Feature{
+ .neon,
+ }),
+ };
+ result[@enumToInt(Feature.armv2)] = .{
+ .llvm_name = "armv2",
+ .description = "ARMv2 architecture",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.armv2a)] = .{
+ .llvm_name = "armv2a",
+ .description = "ARMv2a architecture",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.armv3)] = .{
+ .llvm_name = "armv3",
+ .description = "ARMv3 architecture",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.armv3m)] = .{
+ .llvm_name = "armv3m",
+ .description = "ARMv3m architecture",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.armv4)] = .{
+ .llvm_name = "armv4",
+ .description = "ARMv4 architecture",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.armv4t)] = .{
+ .llvm_name = "armv4t",
+ .description = "ARMv4t architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .v4t,
+ }),
+ };
+ result[@enumToInt(Feature.armv5t)] = .{
+ .llvm_name = "armv5t",
+ .description = "ARMv5t architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .v5t,
+ }),
+ };
+ result[@enumToInt(Feature.armv5te)] = .{
+ .llvm_name = "armv5te",
+ .description = "ARMv5te architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .v5te,
+ }),
+ };
+ result[@enumToInt(Feature.armv5tej)] = .{
+ .llvm_name = "armv5tej",
+ .description = "ARMv5tej architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .v5te,
+ }),
+ };
+ result[@enumToInt(Feature.armv6)] = .{
+ .llvm_name = "armv6",
+ .description = "ARMv6 architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .dsp,
+ .v6,
+ }),
+ };
+ result[@enumToInt(Feature.armv6_m)] = .{
+ .llvm_name = "armv6-m",
+ .description = "ARMv6m architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .db,
+ .mclass,
+ .noarm,
+ .strict_align,
+ .thumb_mode,
+ .v6m,
+ }),
+ };
+ result[@enumToInt(Feature.armv6j)] = .{
+ .llvm_name = "armv6j",
+ .description = "ARMv7a architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .armv6,
+ }),
+ };
+ result[@enumToInt(Feature.armv6k)] = .{
+ .llvm_name = "armv6k",
+ .description = "ARMv6k architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .v6k,
+ }),
+ };
+ result[@enumToInt(Feature.armv6kz)] = .{
+ .llvm_name = "armv6kz",
+ .description = "ARMv6kz architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .trustzone,
+ .v6k,
+ }),
+ };
+ result[@enumToInt(Feature.armv6s_m)] = .{
+ .llvm_name = "armv6s-m",
+ .description = "ARMv6sm architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .db,
+ .mclass,
+ .noarm,
+ .strict_align,
+ .thumb_mode,
+ .v6m,
+ }),
+ };
+ result[@enumToInt(Feature.armv6t2)] = .{
+ .llvm_name = "armv6t2",
+ .description = "ARMv6t2 architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .dsp,
+ .v6t2,
+ }),
+ };
+ result[@enumToInt(Feature.armv7_a)] = .{
+ .llvm_name = "armv7-a",
+ .description = "ARMv7a architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .aclass,
+ .db,
+ .dsp,
+ .neon,
+ .v7,
+ }),
+ };
+ result[@enumToInt(Feature.armv7_m)] = .{
+ .llvm_name = "armv7-m",
+ .description = "ARMv7m architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .db,
+ .hwdiv,
+ .mclass,
+ .noarm,
+ .thumb_mode,
+ .thumb2,
+ .v7,
+ }),
+ };
+ result[@enumToInt(Feature.armv7_r)] = .{
+ .llvm_name = "armv7-r",
+ .description = "ARMv7r architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .db,
+ .dsp,
+ .hwdiv,
+ .rclass,
+ .v7,
+ }),
+ };
+ result[@enumToInt(Feature.armv7e_m)] = .{
+ .llvm_name = "armv7e-m",
+ .description = "ARMv7em architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .db,
+ .dsp,
+ .hwdiv,
+ .mclass,
+ .noarm,
+ .thumb_mode,
+ .thumb2,
+ .v7,
+ }),
+ };
+ result[@enumToInt(Feature.armv7k)] = .{
+ .llvm_name = "armv7k",
+ .description = "ARMv7a architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .armv7_a,
+ }),
+ };
+ result[@enumToInt(Feature.armv7s)] = .{
+ .llvm_name = "armv7s",
+ .description = "ARMv7a architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .armv7_a,
+ }),
+ };
+ result[@enumToInt(Feature.armv7ve)] = .{
+ .llvm_name = "armv7ve",
+ .description = "ARMv7ve architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .aclass,
+ .db,
+ .dsp,
+ .mp,
+ .neon,
+ .trustzone,
+ .v7,
+ .virtualization,
+ }),
+ };
+ result[@enumToInt(Feature.armv8_a)] = .{
+ .llvm_name = "armv8-a",
+ .description = "ARMv8a architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .aclass,
+ .crc,
+ .crypto,
+ .db,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .trustzone,
+ .v8,
+ .virtualization,
+ }),
+ };
+ result[@enumToInt(Feature.armv8_m_base)] = .{
+ .llvm_name = "armv8-m.base",
+ .description = "ARMv8mBaseline architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .@"8msecext",
+ .acquire_release,
+ .db,
+ .hwdiv,
+ .mclass,
+ .noarm,
+ .strict_align,
+ .thumb_mode,
+ .v7clrex,
+ .v8m,
+ }),
+ };
+ result[@enumToInt(Feature.armv8_m_main)] = .{
+ .llvm_name = "armv8-m.main",
+ .description = "ARMv8mMainline architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .@"8msecext",
+ .acquire_release,
+ .db,
+ .hwdiv,
+ .mclass,
+ .noarm,
+ .thumb_mode,
+ .v8m_main,
+ }),
+ };
+ result[@enumToInt(Feature.armv8_r)] = .{
+ .llvm_name = "armv8-r",
+ .description = "ARMv8r architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .db,
+ .dfb,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .rclass,
+ .v8,
+ .virtualization,
+ }),
+ };
+ result[@enumToInt(Feature.armv8_1_a)] = .{
+ .llvm_name = "armv8.1-a",
+ .description = "ARMv81a architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .aclass,
+ .crc,
+ .crypto,
+ .db,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .trustzone,
+ .v8_1a,
+ .virtualization,
+ }),
+ };
+ result[@enumToInt(Feature.armv8_1_m_main)] = .{
+ .llvm_name = "armv8.1-m.main",
+ .description = "ARMv81mMainline architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .@"8msecext",
+ .acquire_release,
+ .db,
+ .hwdiv,
+ .lob,
+ .mclass,
+ .noarm,
+ .ras,
+ .thumb_mode,
+ .v8_1m_main,
+ }),
+ };
+ result[@enumToInt(Feature.armv8_2_a)] = .{
+ .llvm_name = "armv8.2-a",
+ .description = "ARMv82a architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .aclass,
+ .crc,
+ .crypto,
+ .db,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .ras,
+ .trustzone,
+ .v8_2a,
+ .virtualization,
+ }),
+ };
+ result[@enumToInt(Feature.armv8_3_a)] = .{
+ .llvm_name = "armv8.3-a",
+ .description = "ARMv83a architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .aclass,
+ .crc,
+ .crypto,
+ .db,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .ras,
+ .trustzone,
+ .v8_3a,
+ .virtualization,
+ }),
+ };
+ result[@enumToInt(Feature.armv8_4_a)] = .{
+ .llvm_name = "armv8.4-a",
+ .description = "ARMv84a architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .aclass,
+ .crc,
+ .crypto,
+ .db,
+ .dotprod,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .ras,
+ .trustzone,
+ .v8_4a,
+ .virtualization,
+ }),
+ };
+ result[@enumToInt(Feature.armv8_5_a)] = .{
+ .llvm_name = "armv8.5-a",
+ .description = "ARMv85a architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .aclass,
+ .crc,
+ .crypto,
+ .db,
+ .dotprod,
+ .dsp,
+ .fp_armv8,
+ .mp,
+ .neon,
+ .ras,
+ .trustzone,
+ .v8_5a,
+ .virtualization,
+ }),
+ };
+ result[@enumToInt(Feature.avoid_movs_shop)] = .{
+ .llvm_name = "avoid-movs-shop",
+ .description = "Avoid movs instructions with shifter operand",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.avoid_partial_cpsr)] = .{
+ .llvm_name = "avoid-partial-cpsr",
+ .description = "Avoid CPSR partial update for OOO execution",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.cheap_predicable_cpsr)] = .{
+ .llvm_name = "cheap-predicable-cpsr",
+ .description = "Disable +1 predication cost for instructions updating CPSR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.crc)] = .{
+ .llvm_name = "crc",
+ .description = "Enable support for CRC instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.crypto)] = .{
+ .llvm_name = "crypto",
+ .description = "Enable support for Cryptography extensions",
+ .dependencies = featureSet(&[_]Feature{
+ .aes,
+ .neon,
+ .sha2,
+ }),
+ };
+ result[@enumToInt(Feature.d32)] = .{
+ .llvm_name = "d32",
+ .description = "Extend FP to 32 double registers",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.db)] = .{
+ .llvm_name = "db",
+ .description = "Has data barrier (dmb/dsb) instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dfb)] = .{
+ .llvm_name = "dfb",
+ .description = "Has full data barrier (dfb) instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.disable_postra_scheduler)] = .{
+ .llvm_name = "disable-postra-scheduler",
+ .description = "Don't schedule again after register allocation",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dont_widen_vmovs)] = .{
+ .llvm_name = "dont-widen-vmovs",
+ .description = "Don't widen VMOVS to VMOVD",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.dotprod)] = .{
+ .llvm_name = "dotprod",
+ .description = "Enable support for dot product instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .neon,
+ }),
+ };
+ result[@enumToInt(Feature.dsp)] = .{
+ .llvm_name = "dsp",
+ .description = "Supports DSP instructions in ARM and/or Thumb2",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.execute_only)] = .{
+ .llvm_name = "execute-only",
+ .description = "Enable the generation of execute only code.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.expand_fp_mlx)] = .{
+ .llvm_name = "expand-fp-mlx",
+ .description = "Expand VFP/NEON MLA/MLS instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.exynos)] = .{
+ .llvm_name = "exynos",
+ .description = "Samsung Exynos processors",
+ .dependencies = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .expand_fp_mlx,
+ .fuse_aes,
+ .fuse_literals,
+ .hwdiv,
+ .hwdiv_arm,
+ .prof_unpr,
+ .ret_addr_stack,
+ .slow_fp_brcc,
+ .slow_vdup32,
+ .slow_vgetlni32,
+ .slowfpvmlx,
+ .splat_vfp_neon,
+ .use_aa,
+ .wide_stride_vfp,
+ .zcz,
+ }),
+ };
+ result[@enumToInt(Feature.fp_armv8)] = .{
+ .llvm_name = "fp-armv8",
+ .description = "Enable ARMv8 FP",
+ .dependencies = featureSet(&[_]Feature{
+ .fp_armv8d16,
+ .fp_armv8sp,
+ .vfp4,
+ }),
+ };
+ result[@enumToInt(Feature.fp_armv8d16)] = .{
+ .llvm_name = "fp-armv8d16",
+ .description = "Enable ARMv8 FP with only 16 d-registers",
+ .dependencies = featureSet(&[_]Feature{
+ .fp_armv8d16sp,
+ .fp64,
+ .vfp4d16,
+ }),
+ };
+ result[@enumToInt(Feature.fp_armv8d16sp)] = .{
+ .llvm_name = "fp-armv8d16sp",
+ .description = "Enable ARMv8 FP with only 16 d-registers and no double precision",
+ .dependencies = featureSet(&[_]Feature{
+ .vfp4d16sp,
+ }),
+ };
+ result[@enumToInt(Feature.fp_armv8sp)] = .{
+ .llvm_name = "fp-armv8sp",
+ .description = "Enable ARMv8 FP with no double precision",
+ .dependencies = featureSet(&[_]Feature{
+ .d32,
+ .fp_armv8d16sp,
+ .vfp4sp,
+ }),
+ };
+ result[@enumToInt(Feature.fp16)] = .{
+ .llvm_name = "fp16",
+ .description = "Enable half-precision floating point",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fp16fml)] = .{
+ .llvm_name = "fp16fml",
+ .description = "Enable full half-precision floating point fml instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .fullfp16,
+ }),
+ };
+ result[@enumToInt(Feature.fp64)] = .{
+ .llvm_name = "fp64",
+ .description = "Floating point unit supports double precision",
+ .dependencies = featureSet(&[_]Feature{
+ .fpregs64,
+ }),
+ };
+ result[@enumToInt(Feature.fpao)] = .{
+ .llvm_name = "fpao",
+ .description = "Enable fast computation of positive address offsets",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fpregs)] = .{
+ .llvm_name = "fpregs",
+ .description = "Enable FP registers",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fpregs16)] = .{
+ .llvm_name = "fpregs16",
+ .description = "Enable 16-bit FP registers",
+ .dependencies = featureSet(&[_]Feature{
+ .fpregs,
+ }),
+ };
+ result[@enumToInt(Feature.fpregs64)] = .{
+ .llvm_name = "fpregs64",
+ .description = "Enable 64-bit FP registers",
+ .dependencies = featureSet(&[_]Feature{
+ .fpregs,
+ }),
+ };
+ result[@enumToInt(Feature.fullfp16)] = .{
+ .llvm_name = "fullfp16",
+ .description = "Enable full half-precision floating point",
+ .dependencies = featureSet(&[_]Feature{
+ .fp_armv8d16sp,
+ .fpregs16,
+ }),
+ };
+ result[@enumToInt(Feature.fuse_aes)] = .{
+ .llvm_name = "fuse-aes",
+ .description = "CPU fuses AES crypto operations",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fuse_literals)] = .{
+ .llvm_name = "fuse-literals",
+ .description = "CPU fuses literal generation operations",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.hwdiv)] = .{
+ .llvm_name = "hwdiv",
+ .description = "Enable divide instructions in Thumb",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.hwdiv_arm)] = .{
+ .llvm_name = "hwdiv-arm",
+ .description = "Enable divide instructions in ARM mode",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.iwmmxt)] = .{
+ .llvm_name = "iwmmxt",
+ .description = "ARMv5te architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+ result[@enumToInt(Feature.iwmmxt2)] = .{
+ .llvm_name = "iwmmxt2",
+ .description = "ARMv5te architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+ result[@enumToInt(Feature.krait)] = .{
+ .llvm_name = "krait",
+ .description = "Qualcomm Krait processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.kryo)] = .{
+ .llvm_name = "kryo",
+ .description = "Qualcomm Kryo processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.lob)] = .{
+ .llvm_name = "lob",
+ .description = "Enable Low Overhead Branch extensions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.long_calls)] = .{
+ .llvm_name = "long-calls",
+ .description = "Generate calls via indirect call instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.loop_align)] = .{
+ .llvm_name = "loop-align",
+ .description = "Prefer 32-bit alignment for loops",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.m3)] = .{
+ .llvm_name = "m3",
+ .description = "Cortex-M3 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.mclass)] = .{
+ .llvm_name = "mclass",
+ .description = "Is microcontroller profile ('M' series)",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.mp)] = .{
+ .llvm_name = "mp",
+ .description = "Supports Multiprocessing extension",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.muxed_units)] = .{
+ .llvm_name = "muxed-units",
+ .description = "Has muxed AGU and NEON/FPU",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.mve)] = .{
+ .llvm_name = "mve",
+ .description = "Support M-Class Vector Extension with integer ops",
+ .dependencies = featureSet(&[_]Feature{
+ .dsp,
+ .fpregs16,
+ .fpregs64,
+ .v8_1m_main,
+ }),
+ };
+ result[@enumToInt(Feature.mve_fp)] = .{
+ .llvm_name = "mve.fp",
+ .description = "Support M-Class Vector Extension with integer and floating ops",
+ .dependencies = featureSet(&[_]Feature{
+ .fp_armv8d16sp,
+ .fullfp16,
+ .mve,
+ }),
+ };
+ result[@enumToInt(Feature.nacl_trap)] = .{
+ .llvm_name = "nacl-trap",
+ .description = "NaCl trap",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.neon)] = .{
+ .llvm_name = "neon",
+ .description = "Enable NEON instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .vfp3,
+ }),
+ };
+ result[@enumToInt(Feature.neon_fpmovs)] = .{
+ .llvm_name = "neon-fpmovs",
+ .description = "Convert VMOVSR, VMOVRS, VMOVS to NEON",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.neonfp)] = .{
+ .llvm_name = "neonfp",
+ .description = "Use NEON for single precision FP",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.no_branch_predictor)] = .{
+ .llvm_name = "no-branch-predictor",
+ .description = "Has no branch predictor",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.no_movt)] = .{
+ .llvm_name = "no-movt",
+ .description = "Don't use movt/movw pairs for 32-bit imms",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.no_neg_immediates)] = .{
+ .llvm_name = "no-neg-immediates",
+ .description = "Convert immediates and instructions to their negated or complemented equivalent when the immediate does not fit in the encoding.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.noarm)] = .{
+ .llvm_name = "noarm",
+ .description = "Does not support ARM mode execution",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.nonpipelined_vfp)] = .{
+ .llvm_name = "nonpipelined-vfp",
+ .description = "VFP instructions are not pipelined",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.perfmon)] = .{
+ .llvm_name = "perfmon",
+ .description = "Enable support for Performance Monitor extensions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.prefer_ishst)] = .{
+ .llvm_name = "prefer-ishst",
+ .description = "Prefer ISHST barriers",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.prefer_vmovsr)] = .{
+ .llvm_name = "prefer-vmovsr",
+ .description = "Prefer VMOVSR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.prof_unpr)] = .{
+ .llvm_name = "prof-unpr",
+ .description = "Is profitable to unpredicate",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.r4)] = .{
+ .llvm_name = "r4",
+ .description = "Cortex-R4 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.r5)] = .{
+ .llvm_name = "r5",
+ .description = "Cortex-R5 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.r52)] = .{
+ .llvm_name = "r52",
+ .description = "Cortex-R52 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.r7)] = .{
+ .llvm_name = "r7",
+ .description = "Cortex-R7 ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ras)] = .{
+ .llvm_name = "ras",
+ .description = "Enable Reliability, Availability and Serviceability extensions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.rclass)] = .{
+ .llvm_name = "rclass",
+ .description = "Is realtime profile ('R' series)",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.read_tp_hard)] = .{
+ .llvm_name = "read-tp-hard",
+ .description = "Reading thread pointer from register",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.reserve_r9)] = .{
+ .llvm_name = "reserve-r9",
+ .description = "Reserve R9, making it unavailable as GPR",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ret_addr_stack)] = .{
+ .llvm_name = "ret-addr-stack",
+ .description = "Has return address stack",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sb)] = .{
+ .llvm_name = "sb",
+ .description = "Enable v8.5a Speculation Barrier",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sha2)] = .{
+ .llvm_name = "sha2",
+ .description = "Enable SHA1 and SHA256 support",
+ .dependencies = featureSet(&[_]Feature{
+ .neon,
+ }),
+ };
+ result[@enumToInt(Feature.slow_fp_brcc)] = .{
+ .llvm_name = "slow-fp-brcc",
+ .description = "FP compare + branch is slow",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_load_D_subreg)] = .{
+ .llvm_name = "slow-load-D-subreg",
+ .description = "Loading into D subregs is slow",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_odd_reg)] = .{
+ .llvm_name = "slow-odd-reg",
+ .description = "VLDM/VSTM starting with an odd register is slow",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_vdup32)] = .{
+ .llvm_name = "slow-vdup32",
+ .description = "Has slow VDUP32 - prefer VMOV",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_vgetlni32)] = .{
+ .llvm_name = "slow-vgetlni32",
+ .description = "Has slow VGETLNi32 - prefer VMOV",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slowfpvmlx)] = .{
+ .llvm_name = "slowfpvmlx",
+ .description = "Disable VFP / NEON MAC instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.soft_float)] = .{
+ .llvm_name = "soft-float",
+ .description = "Use software floating point features.",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.splat_vfp_neon)] = .{
+ .llvm_name = "splat-vfp-neon",
+ .description = "Splat register from VFP to NEON",
+ .dependencies = featureSet(&[_]Feature{
+ .dont_widen_vmovs,
+ }),
+ };
+ result[@enumToInt(Feature.strict_align)] = .{
+ .llvm_name = "strict-align",
+ .description = "Disallow all unaligned memory access",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.swift)] = .{
+ .llvm_name = "swift",
+ .description = "Swift ARM processors",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.thumb_mode)] = .{
+ .llvm_name = "thumb-mode",
+ .description = "Thumb mode",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.thumb2)] = .{
+ .llvm_name = "thumb2",
+ .description = "Enable Thumb2 instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.trustzone)] = .{
+ .llvm_name = "trustzone",
+ .description = "Enable support for TrustZone security extensions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.use_aa)] = .{
+ .llvm_name = "use-aa",
+ .description = "Use alias analysis during codegen",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.use_misched)] = .{
+ .llvm_name = "use-misched",
+ .description = "Use the MachineScheduler",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.v4t)] = .{
+ .llvm_name = "v4t",
+ .description = "Support ARM v4T instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.v5t)] = .{
+ .llvm_name = "v5t",
+ .description = "Support ARM v5T instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .v4t,
+ }),
+ };
+ result[@enumToInt(Feature.v5te)] = .{
+ .llvm_name = "v5te",
+ .description = "Support ARM v5TE, v5TEj, and v5TExp instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .v5t,
+ }),
+ };
+ result[@enumToInt(Feature.v6)] = .{
+ .llvm_name = "v6",
+ .description = "Support ARM v6 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .v5te,
+ }),
+ };
+ result[@enumToInt(Feature.v6k)] = .{
+ .llvm_name = "v6k",
+ .description = "Support ARM v6k instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .v6,
+ }),
+ };
+ result[@enumToInt(Feature.v6m)] = .{
+ .llvm_name = "v6m",
+ .description = "Support ARM v6M instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .v6,
+ }),
+ };
+ result[@enumToInt(Feature.v6t2)] = .{
+ .llvm_name = "v6t2",
+ .description = "Support ARM v6t2 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .thumb2,
+ .v6k,
+ .v8m,
+ }),
+ };
+ result[@enumToInt(Feature.v7)] = .{
+ .llvm_name = "v7",
+ .description = "Support ARM v7 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .perfmon,
+ .v6t2,
+ .v7clrex,
+ }),
+ };
+ result[@enumToInt(Feature.v7clrex)] = .{
+ .llvm_name = "v7clrex",
+ .description = "Has v7 clrex instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.v8)] = .{
+ .llvm_name = "v8",
+ .description = "Support ARM v8 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .acquire_release,
+ .v7,
+ }),
+ };
+ result[@enumToInt(Feature.v8_1a)] = .{
+ .llvm_name = "v8.1a",
+ .description = "Support ARM v8.1a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .v8,
+ }),
+ };
+ result[@enumToInt(Feature.v8_1m_main)] = .{
+ .llvm_name = "v8.1m.main",
+ .description = "Support ARM v8-1M Mainline instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .v8m_main,
+ }),
+ };
+ result[@enumToInt(Feature.v8_2a)] = .{
+ .llvm_name = "v8.2a",
+ .description = "Support ARM v8.2a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .v8_1a,
+ }),
+ };
+ result[@enumToInt(Feature.v8_3a)] = .{
+ .llvm_name = "v8.3a",
+ .description = "Support ARM v8.3a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .v8_2a,
+ }),
+ };
+ result[@enumToInt(Feature.v8_4a)] = .{
+ .llvm_name = "v8.4a",
+ .description = "Support ARM v8.4a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .dotprod,
+ .v8_3a,
+ }),
+ };
+ result[@enumToInt(Feature.v8_5a)] = .{
+ .llvm_name = "v8.5a",
+ .description = "Support ARM v8.5a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sb,
+ .v8_4a,
+ }),
+ };
+ result[@enumToInt(Feature.v8m)] = .{
+ .llvm_name = "v8m",
+ .description = "Support ARM v8M Baseline instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .v6m,
+ }),
+ };
+ result[@enumToInt(Feature.v8m_main)] = .{
+ .llvm_name = "v8m.main",
+ .description = "Support ARM v8M Mainline instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .v7,
+ }),
+ };
+ result[@enumToInt(Feature.vfp2)] = .{
+ .llvm_name = "vfp2",
+ .description = "Enable VFP2 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .vfp2d16,
+ .vfp2sp,
+ }),
+ };
+ result[@enumToInt(Feature.vfp2d16)] = .{
+ .llvm_name = "vfp2d16",
+ .description = "Enable VFP2 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .fp64,
+ .vfp2d16sp,
+ }),
+ };
+ result[@enumToInt(Feature.vfp2d16sp)] = .{
+ .llvm_name = "vfp2d16sp",
+ .description = "Enable VFP2 instructions with no double precision",
+ .dependencies = featureSet(&[_]Feature{
+ .fpregs,
+ }),
+ };
+ result[@enumToInt(Feature.vfp2sp)] = .{
+ .llvm_name = "vfp2sp",
+ .description = "Enable VFP2 instructions with no double precision",
+ .dependencies = featureSet(&[_]Feature{
+ .vfp2d16sp,
+ }),
+ };
+ result[@enumToInt(Feature.vfp3)] = .{
+ .llvm_name = "vfp3",
+ .description = "Enable VFP3 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .vfp3d16,
+ .vfp3sp,
+ }),
+ };
+ result[@enumToInt(Feature.vfp3d16)] = .{
+ .llvm_name = "vfp3d16",
+ .description = "Enable VFP3 instructions with only 16 d-registers",
+ .dependencies = featureSet(&[_]Feature{
+ .fp64,
+ .vfp2,
+ .vfp3d16sp,
+ }),
+ };
+ result[@enumToInt(Feature.vfp3d16sp)] = .{
+ .llvm_name = "vfp3d16sp",
+ .description = "Enable VFP3 instructions with only 16 d-registers and no double precision",
+ .dependencies = featureSet(&[_]Feature{
+ .vfp2sp,
+ }),
+ };
+ result[@enumToInt(Feature.vfp3sp)] = .{
+ .llvm_name = "vfp3sp",
+ .description = "Enable VFP3 instructions with no double precision",
+ .dependencies = featureSet(&[_]Feature{
+ .d32,
+ .vfp3d16sp,
+ }),
+ };
+ result[@enumToInt(Feature.vfp4)] = .{
+ .llvm_name = "vfp4",
+ .description = "Enable VFP4 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .fp16,
+ .vfp3,
+ .vfp4d16,
+ .vfp4sp,
+ }),
+ };
+ result[@enumToInt(Feature.vfp4d16)] = .{
+ .llvm_name = "vfp4d16",
+ .description = "Enable VFP4 instructions with only 16 d-registers",
+ .dependencies = featureSet(&[_]Feature{
+ .fp16,
+ .fp64,
+ .vfp3d16,
+ .vfp4d16sp,
+ }),
+ };
+ result[@enumToInt(Feature.vfp4d16sp)] = .{
+ .llvm_name = "vfp4d16sp",
+ .description = "Enable VFP4 instructions with only 16 d-registers and no double precision",
+ .dependencies = featureSet(&[_]Feature{
+ .fp16,
+ .vfp3d16sp,
+ }),
+ };
+ result[@enumToInt(Feature.vfp4sp)] = .{
+ .llvm_name = "vfp4sp",
+ .description = "Enable VFP4 instructions with no double precision",
+ .dependencies = featureSet(&[_]Feature{
+ .d32,
+ .fp16,
+ .vfp3sp,
+ .vfp4d16sp,
+ }),
+ };
+ result[@enumToInt(Feature.virtualization)] = .{
+ .llvm_name = "virtualization",
+ .description = "Supports Virtualization extension",
+ .dependencies = featureSet(&[_]Feature{
+ .hwdiv,
+ .hwdiv_arm,
+ }),
+ };
+ result[@enumToInt(Feature.vldn_align)] = .{
+ .llvm_name = "vldn-align",
+ .description = "Check for VLDn unaligned access",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.vmlx_forwarding)] = .{
+ .llvm_name = "vmlx-forwarding",
+ .description = "Has multiplier accumulator forwarding",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.vmlx_hazards)] = .{
+ .llvm_name = "vmlx-hazards",
+ .description = "Has VMLx hazards",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.wide_stride_vfp)] = .{
+ .llvm_name = "wide-stride-vfp",
+ .description = "Use a wide stride when allocating VFP registers",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.xscale)] = .{
+ .llvm_name = "xscale",
+ .description = "ARMv5te architecture",
+ .dependencies = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+ result[@enumToInt(Feature.zcz)] = .{
+ .llvm_name = "zcz",
+ .description = "Has zero-cycle zeroing 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 arm1020e = Cpu{
+ .name = "arm1020e",
+ .llvm_name = "arm1020e",
+ .features = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+ pub const arm1020t = Cpu{
+ .name = "arm1020t",
+ .llvm_name = "arm1020t",
+ .features = featureSet(&[_]Feature{
+ .armv5t,
+ }),
+ };
+ pub const arm1022e = Cpu{
+ .name = "arm1022e",
+ .llvm_name = "arm1022e",
+ .features = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+ pub const arm10e = Cpu{
+ .name = "arm10e",
+ .llvm_name = "arm10e",
+ .features = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+ pub const arm10tdmi = Cpu{
+ .name = "arm10tdmi",
+ .llvm_name = "arm10tdmi",
+ .features = featureSet(&[_]Feature{
+ .armv5t,
+ }),
+ };
+ pub const arm1136j_s = Cpu{
+ .name = "arm1136j_s",
+ .llvm_name = "arm1136j-s",
+ .features = featureSet(&[_]Feature{
+ .armv6,
+ }),
+ };
+ pub const arm1136jf_s = Cpu{
+ .name = "arm1136jf_s",
+ .llvm_name = "arm1136jf-s",
+ .features = featureSet(&[_]Feature{
+ .armv6,
+ .slowfpvmlx,
+ .vfp2,
+ }),
+ };
+ pub const arm1156t2_s = Cpu{
+ .name = "arm1156t2_s",
+ .llvm_name = "arm1156t2-s",
+ .features = featureSet(&[_]Feature{
+ .armv6t2,
+ }),
+ };
+ pub const arm1156t2f_s = Cpu{
+ .name = "arm1156t2f_s",
+ .llvm_name = "arm1156t2f-s",
+ .features = featureSet(&[_]Feature{
+ .armv6t2,
+ .slowfpvmlx,
+ .vfp2,
+ }),
+ };
+ pub const arm1176j_s = Cpu{
+ .name = "arm1176j_s",
+ .llvm_name = "arm1176j-s",
+ .features = featureSet(&[_]Feature{
+ .armv6kz,
+ }),
+ };
+ pub const arm1176jz_s = Cpu{
+ .name = "arm1176jz_s",
+ .llvm_name = "arm1176jz-s",
+ .features = featureSet(&[_]Feature{
+ .armv6kz,
+ }),
+ };
+ pub const arm1176jzf_s = Cpu{
+ .name = "arm1176jzf_s",
+ .llvm_name = "arm1176jzf-s",
+ .features = featureSet(&[_]Feature{
+ .armv6kz,
+ .slowfpvmlx,
+ .vfp2,
+ }),
+ };
+ pub const arm710t = Cpu{
+ .name = "arm710t",
+ .llvm_name = "arm710t",
+ .features = featureSet(&[_]Feature{
+ .armv4t,
+ }),
+ };
+ pub const arm720t = Cpu{
+ .name = "arm720t",
+ .llvm_name = "arm720t",
+ .features = featureSet(&[_]Feature{
+ .armv4t,
+ }),
+ };
+ pub const arm7tdmi = Cpu{
+ .name = "arm7tdmi",
+ .llvm_name = "arm7tdmi",
+ .features = featureSet(&[_]Feature{
+ .armv4t,
+ }),
+ };
+ pub const arm7tdmi_s = Cpu{
+ .name = "arm7tdmi_s",
+ .llvm_name = "arm7tdmi-s",
+ .features = featureSet(&[_]Feature{
+ .armv4t,
+ }),
+ };
+ pub const arm8 = Cpu{
+ .name = "arm8",
+ .llvm_name = "arm8",
+ .features = featureSet(&[_]Feature{
+ .armv4,
+ }),
+ };
+ pub const arm810 = Cpu{
+ .name = "arm810",
+ .llvm_name = "arm810",
+ .features = featureSet(&[_]Feature{
+ .armv4,
+ }),
+ };
+ pub const arm9 = Cpu{
+ .name = "arm9",
+ .llvm_name = "arm9",
+ .features = featureSet(&[_]Feature{
+ .armv4t,
+ }),
+ };
+ pub const arm920 = Cpu{
+ .name = "arm920",
+ .llvm_name = "arm920",
+ .features = featureSet(&[_]Feature{
+ .armv4t,
+ }),
+ };
+ pub const arm920t = Cpu{
+ .name = "arm920t",
+ .llvm_name = "arm920t",
+ .features = featureSet(&[_]Feature{
+ .armv4t,
+ }),
+ };
+ pub const arm922t = Cpu{
+ .name = "arm922t",
+ .llvm_name = "arm922t",
+ .features = featureSet(&[_]Feature{
+ .armv4t,
+ }),
+ };
+ pub const arm926ej_s = Cpu{
+ .name = "arm926ej_s",
+ .llvm_name = "arm926ej-s",
+ .features = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+ pub const arm940t = Cpu{
+ .name = "arm940t",
+ .llvm_name = "arm940t",
+ .features = featureSet(&[_]Feature{
+ .armv4t,
+ }),
+ };
+ pub const arm946e_s = Cpu{
+ .name = "arm946e_s",
+ .llvm_name = "arm946e-s",
+ .features = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+ pub const arm966e_s = Cpu{
+ .name = "arm966e_s",
+ .llvm_name = "arm966e-s",
+ .features = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+ pub const arm968e_s = Cpu{
+ .name = "arm968e_s",
+ .llvm_name = "arm968e-s",
+ .features = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+ pub const arm9e = Cpu{
+ .name = "arm9e",
+ .llvm_name = "arm9e",
+ .features = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+ pub const arm9tdmi = Cpu{
+ .name = "arm9tdmi",
+ .llvm_name = "arm9tdmi",
+ .features = featureSet(&[_]Feature{
+ .armv4t,
+ }),
+ };
+ pub const cortex_a12 = Cpu{
+ .name = "cortex_a12",
+ .llvm_name = "cortex-a12",
+ .features = featureSet(&[_]Feature{
+ .a12,
+ .armv7_a,
+ .avoid_partial_cpsr,
+ .mp,
+ .ret_addr_stack,
+ .trustzone,
+ .vfp4,
+ .virtualization,
+ .vmlx_forwarding,
+ }),
+ };
+ pub const cortex_a15 = Cpu{
+ .name = "cortex_a15",
+ .llvm_name = "cortex-a15",
+ .features = featureSet(&[_]Feature{
+ .a15,
+ .armv7_a,
+ .avoid_partial_cpsr,
+ .dont_widen_vmovs,
+ .mp,
+ .muxed_units,
+ .ret_addr_stack,
+ .splat_vfp_neon,
+ .trustzone,
+ .vfp4,
+ .virtualization,
+ .vldn_align,
+ }),
+ };
+ pub const cortex_a17 = Cpu{
+ .name = "cortex_a17",
+ .llvm_name = "cortex-a17",
+ .features = featureSet(&[_]Feature{
+ .a17,
+ .armv7_a,
+ .avoid_partial_cpsr,
+ .mp,
+ .ret_addr_stack,
+ .trustzone,
+ .vfp4,
+ .virtualization,
+ .vmlx_forwarding,
+ }),
+ };
+ pub const cortex_a32 = Cpu{
+ .name = "cortex_a32",
+ .llvm_name = "cortex-a32",
+ .features = featureSet(&[_]Feature{
+ .armv8_a,
+ .crc,
+ .crypto,
+ .hwdiv,
+ .hwdiv_arm,
+ }),
+ };
+ pub const cortex_a35 = Cpu{
+ .name = "cortex_a35",
+ .llvm_name = "cortex-a35",
+ .features = featureSet(&[_]Feature{
+ .a35,
+ .armv8_a,
+ .crc,
+ .crypto,
+ .hwdiv,
+ .hwdiv_arm,
+ }),
+ };
+ pub const cortex_a5 = Cpu{
+ .name = "cortex_a5",
+ .llvm_name = "cortex-a5",
+ .features = featureSet(&[_]Feature{
+ .a5,
+ .armv7_a,
+ .mp,
+ .ret_addr_stack,
+ .slow_fp_brcc,
+ .slowfpvmlx,
+ .trustzone,
+ .vfp4,
+ .vmlx_forwarding,
+ }),
+ };
+ pub const cortex_a53 = Cpu{
+ .name = "cortex_a53",
+ .llvm_name = "cortex-a53",
+ .features = featureSet(&[_]Feature{
+ .a53,
+ .armv8_a,
+ .crc,
+ .crypto,
+ .fpao,
+ .hwdiv,
+ .hwdiv_arm,
+ }),
+ };
+ pub const cortex_a55 = Cpu{
+ .name = "cortex_a55",
+ .llvm_name = "cortex-a55",
+ .features = featureSet(&[_]Feature{
+ .a55,
+ .armv8_2_a,
+ .dotprod,
+ .hwdiv,
+ .hwdiv_arm,
+ }),
+ };
+ pub const cortex_a57 = Cpu{
+ .name = "cortex_a57",
+ .llvm_name = "cortex-a57",
+ .features = featureSet(&[_]Feature{
+ .a57,
+ .armv8_a,
+ .avoid_partial_cpsr,
+ .cheap_predicable_cpsr,
+ .crc,
+ .crypto,
+ .fpao,
+ .hwdiv,
+ .hwdiv_arm,
+ }),
+ };
+ pub const cortex_a7 = Cpu{
+ .name = "cortex_a7",
+ .llvm_name = "cortex-a7",
+ .features = featureSet(&[_]Feature{
+ .a7,
+ .armv7_a,
+ .mp,
+ .ret_addr_stack,
+ .slow_fp_brcc,
+ .slowfpvmlx,
+ .trustzone,
+ .vfp4,
+ .virtualization,
+ .vmlx_forwarding,
+ .vmlx_hazards,
+ }),
+ };
+ pub const cortex_a72 = Cpu{
+ .name = "cortex_a72",
+ .llvm_name = "cortex-a72",
+ .features = featureSet(&[_]Feature{
+ .a72,
+ .armv8_a,
+ .crc,
+ .crypto,
+ .hwdiv,
+ .hwdiv_arm,
+ }),
+ };
+ pub const cortex_a73 = Cpu{
+ .name = "cortex_a73",
+ .llvm_name = "cortex-a73",
+ .features = featureSet(&[_]Feature{
+ .a73,
+ .armv8_a,
+ .crc,
+ .crypto,
+ .hwdiv,
+ .hwdiv_arm,
+ }),
+ };
+ pub const cortex_a75 = Cpu{
+ .name = "cortex_a75",
+ .llvm_name = "cortex-a75",
+ .features = featureSet(&[_]Feature{
+ .a75,
+ .armv8_2_a,
+ .dotprod,
+ .hwdiv,
+ .hwdiv_arm,
+ }),
+ };
+ pub const cortex_a76 = Cpu{
+ .name = "cortex_a76",
+ .llvm_name = "cortex-a76",
+ .features = featureSet(&[_]Feature{
+ .a76,
+ .armv8_2_a,
+ .crc,
+ .crypto,
+ .dotprod,
+ .fullfp16,
+ .hwdiv,
+ .hwdiv_arm,
+ }),
+ };
+ pub const cortex_a76ae = Cpu{
+ .name = "cortex_a76ae",
+ .llvm_name = "cortex-a76ae",
+ .features = featureSet(&[_]Feature{
+ .a76,
+ .armv8_2_a,
+ .crc,
+ .crypto,
+ .dotprod,
+ .fullfp16,
+ .hwdiv,
+ .hwdiv_arm,
+ }),
+ };
+ pub const cortex_a8 = Cpu{
+ .name = "cortex_a8",
+ .llvm_name = "cortex-a8",
+ .features = featureSet(&[_]Feature{
+ .a8,
+ .armv7_a,
+ .nonpipelined_vfp,
+ .ret_addr_stack,
+ .slow_fp_brcc,
+ .slowfpvmlx,
+ .trustzone,
+ .vmlx_forwarding,
+ .vmlx_hazards,
+ }),
+ };
+ pub const cortex_a9 = Cpu{
+ .name = "cortex_a9",
+ .llvm_name = "cortex-a9",
+ .features = featureSet(&[_]Feature{
+ .a9,
+ .armv7_a,
+ .avoid_partial_cpsr,
+ .expand_fp_mlx,
+ .fp16,
+ .mp,
+ .muxed_units,
+ .neon_fpmovs,
+ .prefer_vmovsr,
+ .ret_addr_stack,
+ .trustzone,
+ .vldn_align,
+ .vmlx_forwarding,
+ .vmlx_hazards,
+ }),
+ };
+ pub const cortex_m0 = Cpu{
+ .name = "cortex_m0",
+ .llvm_name = "cortex-m0",
+ .features = featureSet(&[_]Feature{
+ .armv6_m,
+ }),
+ };
+ pub const cortex_m0plus = Cpu{
+ .name = "cortex_m0plus",
+ .llvm_name = "cortex-m0plus",
+ .features = featureSet(&[_]Feature{
+ .armv6_m,
+ }),
+ };
+ pub const cortex_m1 = Cpu{
+ .name = "cortex_m1",
+ .llvm_name = "cortex-m1",
+ .features = featureSet(&[_]Feature{
+ .armv6_m,
+ }),
+ };
+ pub const cortex_m23 = Cpu{
+ .name = "cortex_m23",
+ .llvm_name = "cortex-m23",
+ .features = featureSet(&[_]Feature{
+ .armv8_m_base,
+ .no_movt,
+ }),
+ };
+ pub const cortex_m3 = Cpu{
+ .name = "cortex_m3",
+ .llvm_name = "cortex-m3",
+ .features = featureSet(&[_]Feature{
+ .armv7_m,
+ .loop_align,
+ .m3,
+ .no_branch_predictor,
+ .use_aa,
+ .use_misched,
+ }),
+ };
+ pub const cortex_m33 = Cpu{
+ .name = "cortex_m33",
+ .llvm_name = "cortex-m33",
+ .features = featureSet(&[_]Feature{
+ .armv8_m_main,
+ .dsp,
+ .fp_armv8d16sp,
+ .loop_align,
+ .no_branch_predictor,
+ .slowfpvmlx,
+ .use_aa,
+ .use_misched,
+ }),
+ };
+ pub const cortex_m35p = Cpu{
+ .name = "cortex_m35p",
+ .llvm_name = "cortex-m35p",
+ .features = featureSet(&[_]Feature{
+ .armv8_m_main,
+ .dsp,
+ .fp_armv8d16sp,
+ .loop_align,
+ .no_branch_predictor,
+ .slowfpvmlx,
+ .use_aa,
+ .use_misched,
+ }),
+ };
+ pub const cortex_m4 = Cpu{
+ .name = "cortex_m4",
+ .llvm_name = "cortex-m4",
+ .features = featureSet(&[_]Feature{
+ .armv7e_m,
+ .loop_align,
+ .no_branch_predictor,
+ .slowfpvmlx,
+ .use_aa,
+ .use_misched,
+ .vfp4d16sp,
+ }),
+ };
+ pub const cortex_m7 = Cpu{
+ .name = "cortex_m7",
+ .llvm_name = "cortex-m7",
+ .features = featureSet(&[_]Feature{
+ .armv7e_m,
+ .fp_armv8d16,
+ }),
+ };
+ pub const cortex_r4 = Cpu{
+ .name = "cortex_r4",
+ .llvm_name = "cortex-r4",
+ .features = featureSet(&[_]Feature{
+ .armv7_r,
+ .avoid_partial_cpsr,
+ .r4,
+ .ret_addr_stack,
+ }),
+ };
+ pub const cortex_r4f = Cpu{
+ .name = "cortex_r4f",
+ .llvm_name = "cortex-r4f",
+ .features = featureSet(&[_]Feature{
+ .armv7_r,
+ .avoid_partial_cpsr,
+ .r4,
+ .ret_addr_stack,
+ .slow_fp_brcc,
+ .slowfpvmlx,
+ .vfp3d16,
+ }),
+ };
+ pub const cortex_r5 = Cpu{
+ .name = "cortex_r5",
+ .llvm_name = "cortex-r5",
+ .features = featureSet(&[_]Feature{
+ .armv7_r,
+ .avoid_partial_cpsr,
+ .hwdiv_arm,
+ .r5,
+ .ret_addr_stack,
+ .slow_fp_brcc,
+ .slowfpvmlx,
+ .vfp3d16,
+ }),
+ };
+ pub const cortex_r52 = Cpu{
+ .name = "cortex_r52",
+ .llvm_name = "cortex-r52",
+ .features = featureSet(&[_]Feature{
+ .armv8_r,
+ .fpao,
+ .r52,
+ .use_aa,
+ .use_misched,
+ }),
+ };
+ pub const cortex_r7 = Cpu{
+ .name = "cortex_r7",
+ .llvm_name = "cortex-r7",
+ .features = featureSet(&[_]Feature{
+ .armv7_r,
+ .avoid_partial_cpsr,
+ .fp16,
+ .hwdiv_arm,
+ .mp,
+ .r7,
+ .ret_addr_stack,
+ .slow_fp_brcc,
+ .slowfpvmlx,
+ .vfp3d16,
+ }),
+ };
+ pub const cortex_r8 = Cpu{
+ .name = "cortex_r8",
+ .llvm_name = "cortex-r8",
+ .features = featureSet(&[_]Feature{
+ .armv7_r,
+ .avoid_partial_cpsr,
+ .fp16,
+ .hwdiv_arm,
+ .mp,
+ .ret_addr_stack,
+ .slow_fp_brcc,
+ .slowfpvmlx,
+ .vfp3d16,
+ }),
+ };
+ pub const cyclone = Cpu{
+ .name = "cyclone",
+ .llvm_name = "cyclone",
+ .features = featureSet(&[_]Feature{
+ .armv8_a,
+ .avoid_movs_shop,
+ .avoid_partial_cpsr,
+ .crypto,
+ .disable_postra_scheduler,
+ .hwdiv,
+ .hwdiv_arm,
+ .mp,
+ .neonfp,
+ .ret_addr_stack,
+ .slowfpvmlx,
+ .swift,
+ .use_misched,
+ .vfp4,
+ .zcz,
+ }),
+ };
+ pub const ep9312 = Cpu{
+ .name = "ep9312",
+ .llvm_name = "ep9312",
+ .features = featureSet(&[_]Feature{
+ .armv4t,
+ }),
+ };
+ pub const exynos_m1 = Cpu{
+ .name = "exynos_m1",
+ .llvm_name = "exynos-m1",
+ .features = featureSet(&[_]Feature{
+ .armv8_a,
+ .exynos,
+ }),
+ };
+ pub const exynos_m2 = Cpu{
+ .name = "exynos_m2",
+ .llvm_name = "exynos-m2",
+ .features = featureSet(&[_]Feature{
+ .armv8_a,
+ .exynos,
+ }),
+ };
+ pub const exynos_m3 = Cpu{
+ .name = "exynos_m3",
+ .llvm_name = "exynos-m3",
+ .features = featureSet(&[_]Feature{
+ .armv8_a,
+ .exynos,
+ }),
+ };
+ pub const exynos_m4 = Cpu{
+ .name = "exynos_m4",
+ .llvm_name = "exynos-m4",
+ .features = featureSet(&[_]Feature{
+ .armv8_2_a,
+ .dotprod,
+ .exynos,
+ .fullfp16,
+ }),
+ };
+ pub const exynos_m5 = Cpu{
+ .name = "exynos_m5",
+ .llvm_name = "exynos-m5",
+ .features = featureSet(&[_]Feature{
+ .armv8_2_a,
+ .dotprod,
+ .exynos,
+ .fullfp16,
+ }),
+ };
+ pub const generic = Cpu{
+ .name = "generic",
+ .llvm_name = "generic",
+ .features = featureSet(&[_]Feature{}),
+ };
+ pub const iwmmxt = Cpu{
+ .name = "iwmmxt",
+ .llvm_name = "iwmmxt",
+ .features = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+ pub const krait = Cpu{
+ .name = "krait",
+ .llvm_name = "krait",
+ .features = featureSet(&[_]Feature{
+ .armv7_a,
+ .avoid_partial_cpsr,
+ .fp16,
+ .hwdiv,
+ .hwdiv_arm,
+ .krait,
+ .muxed_units,
+ .ret_addr_stack,
+ .vfp4,
+ .vldn_align,
+ .vmlx_forwarding,
+ }),
+ };
+ pub const kryo = Cpu{
+ .name = "kryo",
+ .llvm_name = "kryo",
+ .features = featureSet(&[_]Feature{
+ .armv8_a,
+ .crc,
+ .crypto,
+ .hwdiv,
+ .hwdiv_arm,
+ .kryo,
+ }),
+ };
+ pub const mpcore = Cpu{
+ .name = "mpcore",
+ .llvm_name = "mpcore",
+ .features = featureSet(&[_]Feature{
+ .armv6k,
+ .slowfpvmlx,
+ .vfp2,
+ }),
+ };
+ pub const mpcorenovfp = Cpu{
+ .name = "mpcorenovfp",
+ .llvm_name = "mpcorenovfp",
+ .features = featureSet(&[_]Feature{
+ .armv6k,
+ }),
+ };
+ pub const sc000 = Cpu{
+ .name = "sc000",
+ .llvm_name = "sc000",
+ .features = featureSet(&[_]Feature{
+ .armv6_m,
+ }),
+ };
+ pub const sc300 = Cpu{
+ .name = "sc300",
+ .llvm_name = "sc300",
+ .features = featureSet(&[_]Feature{
+ .armv7_m,
+ .m3,
+ .no_branch_predictor,
+ .use_aa,
+ .use_misched,
+ }),
+ };
+ pub const strongarm = Cpu{
+ .name = "strongarm",
+ .llvm_name = "strongarm",
+ .features = featureSet(&[_]Feature{
+ .armv4,
+ }),
+ };
+ pub const strongarm110 = Cpu{
+ .name = "strongarm110",
+ .llvm_name = "strongarm110",
+ .features = featureSet(&[_]Feature{
+ .armv4,
+ }),
+ };
+ pub const strongarm1100 = Cpu{
+ .name = "strongarm1100",
+ .llvm_name = "strongarm1100",
+ .features = featureSet(&[_]Feature{
+ .armv4,
+ }),
+ };
+ pub const strongarm1110 = Cpu{
+ .name = "strongarm1110",
+ .llvm_name = "strongarm1110",
+ .features = featureSet(&[_]Feature{
+ .armv4,
+ }),
+ };
+ pub const swift = Cpu{
+ .name = "swift",
+ .llvm_name = "swift",
+ .features = featureSet(&[_]Feature{
+ .armv7_a,
+ .avoid_movs_shop,
+ .avoid_partial_cpsr,
+ .disable_postra_scheduler,
+ .hwdiv,
+ .hwdiv_arm,
+ .mp,
+ .neonfp,
+ .prefer_ishst,
+ .prof_unpr,
+ .ret_addr_stack,
+ .slow_load_D_subreg,
+ .slow_odd_reg,
+ .slow_vdup32,
+ .slow_vgetlni32,
+ .slowfpvmlx,
+ .swift,
+ .use_misched,
+ .vfp4,
+ .vmlx_hazards,
+ .wide_stride_vfp,
+ }),
+ };
+ pub const xscale = Cpu{
+ .name = "xscale",
+ .llvm_name = "xscale",
+ .features = featureSet(&[_]Feature{
+ .armv5te,
+ }),
+ };
+};
+
+/// All arm 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.arm1020e,
+ &cpu.arm1020t,
+ &cpu.arm1022e,
+ &cpu.arm10e,
+ &cpu.arm10tdmi,
+ &cpu.arm1136j_s,
+ &cpu.arm1136jf_s,
+ &cpu.arm1156t2_s,
+ &cpu.arm1156t2f_s,
+ &cpu.arm1176j_s,
+ &cpu.arm1176jz_s,
+ &cpu.arm1176jzf_s,
+ &cpu.arm710t,
+ &cpu.arm720t,
+ &cpu.arm7tdmi,
+ &cpu.arm7tdmi_s,
+ &cpu.arm8,
+ &cpu.arm810,
+ &cpu.arm9,
+ &cpu.arm920,
+ &cpu.arm920t,
+ &cpu.arm922t,
+ &cpu.arm926ej_s,
+ &cpu.arm940t,
+ &cpu.arm946e_s,
+ &cpu.arm966e_s,
+ &cpu.arm968e_s,
+ &cpu.arm9e,
+ &cpu.arm9tdmi,
+ &cpu.cortex_a12,
+ &cpu.cortex_a15,
+ &cpu.cortex_a17,
+ &cpu.cortex_a32,
+ &cpu.cortex_a35,
+ &cpu.cortex_a5,
+ &cpu.cortex_a53,
+ &cpu.cortex_a55,
+ &cpu.cortex_a57,
+ &cpu.cortex_a7,
+ &cpu.cortex_a72,
+ &cpu.cortex_a73,
+ &cpu.cortex_a75,
+ &cpu.cortex_a76,
+ &cpu.cortex_a76ae,
+ &cpu.cortex_a8,
+ &cpu.cortex_a9,
+ &cpu.cortex_m0,
+ &cpu.cortex_m0plus,
+ &cpu.cortex_m1,
+ &cpu.cortex_m23,
+ &cpu.cortex_m3,
+ &cpu.cortex_m33,
+ &cpu.cortex_m35p,
+ &cpu.cortex_m4,
+ &cpu.cortex_m7,
+ &cpu.cortex_r4,
+ &cpu.cortex_r4f,
+ &cpu.cortex_r5,
+ &cpu.cortex_r52,
+ &cpu.cortex_r7,
+ &cpu.cortex_r8,
+ &cpu.cyclone,
+ &cpu.ep9312,
+ &cpu.exynos_m1,
+ &cpu.exynos_m2,
+ &cpu.exynos_m3,
+ &cpu.exynos_m4,
+ &cpu.exynos_m5,
+ &cpu.generic,
+ &cpu.iwmmxt,
+ &cpu.krait,
+ &cpu.kryo,
+ &cpu.mpcore,
+ &cpu.mpcorenovfp,
+ &cpu.sc000,
+ &cpu.sc300,
+ &cpu.strongarm,
+ &cpu.strongarm110,
+ &cpu.strongarm1100,
+ &cpu.strongarm1110,
+ &cpu.swift,
+ &cpu.xscale,
+};
diff --git a/lib/std/target/avr.zig b/lib/std/target/avr.zig
new file mode 100644
index 0000000000..3902a3860f
--- /dev/null
+++ b/lib/std/target/avr.zig
@@ -0,0 +1,2380 @@
+const std = @import("../std.zig");
+const Cpu = std.Target.Cpu;
+
+pub const Feature = enum {
+ addsubiw,
+ avr0,
+ avr1,
+ avr2,
+ avr25,
+ avr3,
+ avr31,
+ avr35,
+ avr4,
+ avr5,
+ avr51,
+ avr6,
+ avrtiny,
+ @"break",
+ des,
+ eijmpcall,
+ elpm,
+ elpmx,
+ ijmpcall,
+ jmpcall,
+ lpm,
+ lpmx,
+ movw,
+ mul,
+ rmw,
+ smallstack,
+ special,
+ spm,
+ spmx,
+ sram,
+ tinyencoding,
+ xmega,
+ xmegau,
+};
+
+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.addsubiw)] = .{
+ .llvm_name = "addsubiw",
+ .description = "Enable 16-bit register-immediate addition and subtraction instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.avr0)] = .{
+ .llvm_name = "avr0",
+ .description = "The device is a part of the avr0 family",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.avr1)] = .{
+ .llvm_name = "avr1",
+ .description = "The device is a part of the avr1 family",
+ .dependencies = featureSet(&[_]Feature{
+ .avr0,
+ .lpm,
+ }),
+ };
+ result[@enumToInt(Feature.avr2)] = .{
+ .llvm_name = "avr2",
+ .description = "The device is a part of the avr2 family",
+ .dependencies = featureSet(&[_]Feature{
+ .addsubiw,
+ .avr1,
+ .ijmpcall,
+ .sram,
+ }),
+ };
+ result[@enumToInt(Feature.avr25)] = .{
+ .llvm_name = "avr25",
+ .description = "The device is a part of the avr25 family",
+ .dependencies = featureSet(&[_]Feature{
+ .avr2,
+ .@"break",
+ .lpmx,
+ .movw,
+ .spm,
+ }),
+ };
+ result[@enumToInt(Feature.avr3)] = .{
+ .llvm_name = "avr3",
+ .description = "The device is a part of the avr3 family",
+ .dependencies = featureSet(&[_]Feature{
+ .avr2,
+ .jmpcall,
+ }),
+ };
+ result[@enumToInt(Feature.avr31)] = .{
+ .llvm_name = "avr31",
+ .description = "The device is a part of the avr31 family",
+ .dependencies = featureSet(&[_]Feature{
+ .avr3,
+ .elpm,
+ }),
+ };
+ result[@enumToInt(Feature.avr35)] = .{
+ .llvm_name = "avr35",
+ .description = "The device is a part of the avr35 family",
+ .dependencies = featureSet(&[_]Feature{
+ .avr3,
+ .@"break",
+ .lpmx,
+ .movw,
+ .spm,
+ }),
+ };
+ result[@enumToInt(Feature.avr4)] = .{
+ .llvm_name = "avr4",
+ .description = "The device is a part of the avr4 family",
+ .dependencies = featureSet(&[_]Feature{
+ .avr2,
+ .@"break",
+ .lpmx,
+ .movw,
+ .mul,
+ .spm,
+ }),
+ };
+ result[@enumToInt(Feature.avr5)] = .{
+ .llvm_name = "avr5",
+ .description = "The device is a part of the avr5 family",
+ .dependencies = featureSet(&[_]Feature{
+ .avr3,
+ .@"break",
+ .lpmx,
+ .movw,
+ .mul,
+ .spm,
+ }),
+ };
+ result[@enumToInt(Feature.avr51)] = .{
+ .llvm_name = "avr51",
+ .description = "The device is a part of the avr51 family",
+ .dependencies = featureSet(&[_]Feature{
+ .avr5,
+ .elpm,
+ .elpmx,
+ }),
+ };
+ result[@enumToInt(Feature.avr6)] = .{
+ .llvm_name = "avr6",
+ .description = "The device is a part of the avr6 family",
+ .dependencies = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ result[@enumToInt(Feature.avrtiny)] = .{
+ .llvm_name = "avrtiny",
+ .description = "The device is a part of the avrtiny family",
+ .dependencies = featureSet(&[_]Feature{
+ .avr0,
+ .@"break",
+ .sram,
+ .tinyencoding,
+ }),
+ };
+ result[@enumToInt(Feature.@"break")] = .{
+ .llvm_name = "break",
+ .description = "The device supports the `BREAK` debugging instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.des)] = .{
+ .llvm_name = "des",
+ .description = "The device supports the `DES k` encryption instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.eijmpcall)] = .{
+ .llvm_name = "eijmpcall",
+ .description = "The device supports the `EIJMP`/`EICALL` instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.elpm)] = .{
+ .llvm_name = "elpm",
+ .description = "The device supports the ELPM instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.elpmx)] = .{
+ .llvm_name = "elpmx",
+ .description = "The device supports the `ELPM Rd, Z[+]` instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ijmpcall)] = .{
+ .llvm_name = "ijmpcall",
+ .description = "The device supports `IJMP`/`ICALL`instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.jmpcall)] = .{
+ .llvm_name = "jmpcall",
+ .description = "The device supports the `JMP` and `CALL` instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.lpm)] = .{
+ .llvm_name = "lpm",
+ .description = "The device supports the `LPM` instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.lpmx)] = .{
+ .llvm_name = "lpmx",
+ .description = "The device supports the `LPM Rd, Z[+]` instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.movw)] = .{
+ .llvm_name = "movw",
+ .description = "The device supports the 16-bit MOVW instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.mul)] = .{
+ .llvm_name = "mul",
+ .description = "The device supports the multiplication instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.rmw)] = .{
+ .llvm_name = "rmw",
+ .description = "The device supports the read-write-modify instructions: XCH, LAS, LAC, LAT",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.smallstack)] = .{
+ .llvm_name = "smallstack",
+ .description = "The device has an 8-bit stack pointer",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.special)] = .{
+ .llvm_name = "special",
+ .description = "Enable use of the entire instruction set - used for debugging",
+ .dependencies = featureSet(&[_]Feature{
+ .addsubiw,
+ .@"break",
+ .des,
+ .eijmpcall,
+ .elpm,
+ .elpmx,
+ .ijmpcall,
+ .jmpcall,
+ .lpm,
+ .lpmx,
+ .movw,
+ .mul,
+ .rmw,
+ .spm,
+ .spmx,
+ .sram,
+ }),
+ };
+ result[@enumToInt(Feature.spm)] = .{
+ .llvm_name = "spm",
+ .description = "The device supports the `SPM` instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.spmx)] = .{
+ .llvm_name = "spmx",
+ .description = "The device supports the `SPM Z+` instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sram)] = .{
+ .llvm_name = "sram",
+ .description = "The device has random access memory",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.tinyencoding)] = .{
+ .llvm_name = "tinyencoding",
+ .description = "The device has Tiny core specific instruction encodings",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.xmega)] = .{
+ .llvm_name = "xmega",
+ .description = "The device is a part of the xmega family",
+ .dependencies = featureSet(&[_]Feature{
+ .avr51,
+ .des,
+ .eijmpcall,
+ .spmx,
+ }),
+ };
+ result[@enumToInt(Feature.xmegau)] = .{
+ .llvm_name = "xmegau",
+ .description = "The device is a part of the xmegau family",
+ .dependencies = featureSet(&[_]Feature{
+ .rmw,
+ .xmega,
+ }),
+ };
+ 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 at43usb320 = Cpu{
+ .name = "at43usb320",
+ .llvm_name = "at43usb320",
+ .features = featureSet(&[_]Feature{
+ .avr31,
+ }),
+ };
+ pub const at43usb355 = Cpu{
+ .name = "at43usb355",
+ .llvm_name = "at43usb355",
+ .features = featureSet(&[_]Feature{
+ .avr3,
+ }),
+ };
+ pub const at76c711 = Cpu{
+ .name = "at76c711",
+ .llvm_name = "at76c711",
+ .features = featureSet(&[_]Feature{
+ .avr3,
+ }),
+ };
+ pub const at86rf401 = Cpu{
+ .name = "at86rf401",
+ .llvm_name = "at86rf401",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ .lpmx,
+ .movw,
+ }),
+ };
+ pub const at90c8534 = Cpu{
+ .name = "at90c8534",
+ .llvm_name = "at90c8534",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ }),
+ };
+ pub const at90can128 = Cpu{
+ .name = "at90can128",
+ .llvm_name = "at90can128",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const at90can32 = Cpu{
+ .name = "at90can32",
+ .llvm_name = "at90can32",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const at90can64 = Cpu{
+ .name = "at90can64",
+ .llvm_name = "at90can64",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const at90pwm1 = Cpu{
+ .name = "at90pwm1",
+ .llvm_name = "at90pwm1",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const at90pwm161 = Cpu{
+ .name = "at90pwm161",
+ .llvm_name = "at90pwm161",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const at90pwm2 = Cpu{
+ .name = "at90pwm2",
+ .llvm_name = "at90pwm2",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const at90pwm216 = Cpu{
+ .name = "at90pwm216",
+ .llvm_name = "at90pwm216",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const at90pwm2b = Cpu{
+ .name = "at90pwm2b",
+ .llvm_name = "at90pwm2b",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const at90pwm3 = Cpu{
+ .name = "at90pwm3",
+ .llvm_name = "at90pwm3",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const at90pwm316 = Cpu{
+ .name = "at90pwm316",
+ .llvm_name = "at90pwm316",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const at90pwm3b = Cpu{
+ .name = "at90pwm3b",
+ .llvm_name = "at90pwm3b",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const at90pwm81 = Cpu{
+ .name = "at90pwm81",
+ .llvm_name = "at90pwm81",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const at90s1200 = Cpu{
+ .name = "at90s1200",
+ .llvm_name = "at90s1200",
+ .features = featureSet(&[_]Feature{
+ .avr0,
+ }),
+ };
+ pub const at90s2313 = Cpu{
+ .name = "at90s2313",
+ .llvm_name = "at90s2313",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ }),
+ };
+ pub const at90s2323 = Cpu{
+ .name = "at90s2323",
+ .llvm_name = "at90s2323",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ }),
+ };
+ pub const at90s2333 = Cpu{
+ .name = "at90s2333",
+ .llvm_name = "at90s2333",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ }),
+ };
+ pub const at90s2343 = Cpu{
+ .name = "at90s2343",
+ .llvm_name = "at90s2343",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ }),
+ };
+ pub const at90s4414 = Cpu{
+ .name = "at90s4414",
+ .llvm_name = "at90s4414",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ }),
+ };
+ pub const at90s4433 = Cpu{
+ .name = "at90s4433",
+ .llvm_name = "at90s4433",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ }),
+ };
+ pub const at90s4434 = Cpu{
+ .name = "at90s4434",
+ .llvm_name = "at90s4434",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ }),
+ };
+ pub const at90s8515 = Cpu{
+ .name = "at90s8515",
+ .llvm_name = "at90s8515",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ }),
+ };
+ pub const at90s8535 = Cpu{
+ .name = "at90s8535",
+ .llvm_name = "at90s8535",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ }),
+ };
+ pub const at90scr100 = Cpu{
+ .name = "at90scr100",
+ .llvm_name = "at90scr100",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const at90usb1286 = Cpu{
+ .name = "at90usb1286",
+ .llvm_name = "at90usb1286",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const at90usb1287 = Cpu{
+ .name = "at90usb1287",
+ .llvm_name = "at90usb1287",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const at90usb162 = Cpu{
+ .name = "at90usb162",
+ .llvm_name = "at90usb162",
+ .features = featureSet(&[_]Feature{
+ .avr35,
+ }),
+ };
+ pub const at90usb646 = Cpu{
+ .name = "at90usb646",
+ .llvm_name = "at90usb646",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const at90usb647 = Cpu{
+ .name = "at90usb647",
+ .llvm_name = "at90usb647",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const at90usb82 = Cpu{
+ .name = "at90usb82",
+ .llvm_name = "at90usb82",
+ .features = featureSet(&[_]Feature{
+ .avr35,
+ }),
+ };
+ pub const at94k = Cpu{
+ .name = "at94k",
+ .llvm_name = "at94k",
+ .features = featureSet(&[_]Feature{
+ .avr3,
+ .lpmx,
+ .movw,
+ .mul,
+ }),
+ };
+ pub const ata5272 = Cpu{
+ .name = "ata5272",
+ .llvm_name = "ata5272",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const ata5505 = Cpu{
+ .name = "ata5505",
+ .llvm_name = "ata5505",
+ .features = featureSet(&[_]Feature{
+ .avr35,
+ }),
+ };
+ pub const ata5790 = Cpu{
+ .name = "ata5790",
+ .llvm_name = "ata5790",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const ata5795 = Cpu{
+ .name = "ata5795",
+ .llvm_name = "ata5795",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const ata6285 = Cpu{
+ .name = "ata6285",
+ .llvm_name = "ata6285",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const ata6286 = Cpu{
+ .name = "ata6286",
+ .llvm_name = "ata6286",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const ata6289 = Cpu{
+ .name = "ata6289",
+ .llvm_name = "ata6289",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const atmega103 = Cpu{
+ .name = "atmega103",
+ .llvm_name = "atmega103",
+ .features = featureSet(&[_]Feature{
+ .avr31,
+ }),
+ };
+ pub const atmega128 = Cpu{
+ .name = "atmega128",
+ .llvm_name = "atmega128",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const atmega1280 = Cpu{
+ .name = "atmega1280",
+ .llvm_name = "atmega1280",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const atmega1281 = Cpu{
+ .name = "atmega1281",
+ .llvm_name = "atmega1281",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const atmega1284 = Cpu{
+ .name = "atmega1284",
+ .llvm_name = "atmega1284",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const atmega1284p = Cpu{
+ .name = "atmega1284p",
+ .llvm_name = "atmega1284p",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const atmega1284rfr2 = Cpu{
+ .name = "atmega1284rfr2",
+ .llvm_name = "atmega1284rfr2",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const atmega128a = Cpu{
+ .name = "atmega128a",
+ .llvm_name = "atmega128a",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const atmega128rfa1 = Cpu{
+ .name = "atmega128rfa1",
+ .llvm_name = "atmega128rfa1",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const atmega128rfr2 = Cpu{
+ .name = "atmega128rfr2",
+ .llvm_name = "atmega128rfr2",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const atmega16 = Cpu{
+ .name = "atmega16",
+ .llvm_name = "atmega16",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega161 = Cpu{
+ .name = "atmega161",
+ .llvm_name = "atmega161",
+ .features = featureSet(&[_]Feature{
+ .avr3,
+ .lpmx,
+ .movw,
+ .mul,
+ .spm,
+ }),
+ };
+ pub const atmega162 = Cpu{
+ .name = "atmega162",
+ .llvm_name = "atmega162",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega163 = Cpu{
+ .name = "atmega163",
+ .llvm_name = "atmega163",
+ .features = featureSet(&[_]Feature{
+ .avr3,
+ .lpmx,
+ .movw,
+ .mul,
+ .spm,
+ }),
+ };
+ pub const atmega164a = Cpu{
+ .name = "atmega164a",
+ .llvm_name = "atmega164a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega164p = Cpu{
+ .name = "atmega164p",
+ .llvm_name = "atmega164p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega164pa = Cpu{
+ .name = "atmega164pa",
+ .llvm_name = "atmega164pa",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega165 = Cpu{
+ .name = "atmega165",
+ .llvm_name = "atmega165",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega165a = Cpu{
+ .name = "atmega165a",
+ .llvm_name = "atmega165a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega165p = Cpu{
+ .name = "atmega165p",
+ .llvm_name = "atmega165p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega165pa = Cpu{
+ .name = "atmega165pa",
+ .llvm_name = "atmega165pa",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega168 = Cpu{
+ .name = "atmega168",
+ .llvm_name = "atmega168",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega168a = Cpu{
+ .name = "atmega168a",
+ .llvm_name = "atmega168a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega168p = Cpu{
+ .name = "atmega168p",
+ .llvm_name = "atmega168p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega168pa = Cpu{
+ .name = "atmega168pa",
+ .llvm_name = "atmega168pa",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega169 = Cpu{
+ .name = "atmega169",
+ .llvm_name = "atmega169",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega169a = Cpu{
+ .name = "atmega169a",
+ .llvm_name = "atmega169a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega169p = Cpu{
+ .name = "atmega169p",
+ .llvm_name = "atmega169p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega169pa = Cpu{
+ .name = "atmega169pa",
+ .llvm_name = "atmega169pa",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega16a = Cpu{
+ .name = "atmega16a",
+ .llvm_name = "atmega16a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega16hva = Cpu{
+ .name = "atmega16hva",
+ .llvm_name = "atmega16hva",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega16hva2 = Cpu{
+ .name = "atmega16hva2",
+ .llvm_name = "atmega16hva2",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega16hvb = Cpu{
+ .name = "atmega16hvb",
+ .llvm_name = "atmega16hvb",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega16hvbrevb = Cpu{
+ .name = "atmega16hvbrevb",
+ .llvm_name = "atmega16hvbrevb",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega16m1 = Cpu{
+ .name = "atmega16m1",
+ .llvm_name = "atmega16m1",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega16u2 = Cpu{
+ .name = "atmega16u2",
+ .llvm_name = "atmega16u2",
+ .features = featureSet(&[_]Feature{
+ .avr35,
+ }),
+ };
+ pub const atmega16u4 = Cpu{
+ .name = "atmega16u4",
+ .llvm_name = "atmega16u4",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega2560 = Cpu{
+ .name = "atmega2560",
+ .llvm_name = "atmega2560",
+ .features = featureSet(&[_]Feature{
+ .avr6,
+ }),
+ };
+ pub const atmega2561 = Cpu{
+ .name = "atmega2561",
+ .llvm_name = "atmega2561",
+ .features = featureSet(&[_]Feature{
+ .avr6,
+ }),
+ };
+ pub const atmega2564rfr2 = Cpu{
+ .name = "atmega2564rfr2",
+ .llvm_name = "atmega2564rfr2",
+ .features = featureSet(&[_]Feature{
+ .avr6,
+ }),
+ };
+ pub const atmega256rfr2 = Cpu{
+ .name = "atmega256rfr2",
+ .llvm_name = "atmega256rfr2",
+ .features = featureSet(&[_]Feature{
+ .avr6,
+ }),
+ };
+ pub const atmega32 = Cpu{
+ .name = "atmega32",
+ .llvm_name = "atmega32",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega323 = Cpu{
+ .name = "atmega323",
+ .llvm_name = "atmega323",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega324a = Cpu{
+ .name = "atmega324a",
+ .llvm_name = "atmega324a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega324p = Cpu{
+ .name = "atmega324p",
+ .llvm_name = "atmega324p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega324pa = Cpu{
+ .name = "atmega324pa",
+ .llvm_name = "atmega324pa",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega325 = Cpu{
+ .name = "atmega325",
+ .llvm_name = "atmega325",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega3250 = Cpu{
+ .name = "atmega3250",
+ .llvm_name = "atmega3250",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega3250a = Cpu{
+ .name = "atmega3250a",
+ .llvm_name = "atmega3250a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega3250p = Cpu{
+ .name = "atmega3250p",
+ .llvm_name = "atmega3250p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega3250pa = Cpu{
+ .name = "atmega3250pa",
+ .llvm_name = "atmega3250pa",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega325a = Cpu{
+ .name = "atmega325a",
+ .llvm_name = "atmega325a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega325p = Cpu{
+ .name = "atmega325p",
+ .llvm_name = "atmega325p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega325pa = Cpu{
+ .name = "atmega325pa",
+ .llvm_name = "atmega325pa",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega328 = Cpu{
+ .name = "atmega328",
+ .llvm_name = "atmega328",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega328p = Cpu{
+ .name = "atmega328p",
+ .llvm_name = "atmega328p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega329 = Cpu{
+ .name = "atmega329",
+ .llvm_name = "atmega329",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega3290 = Cpu{
+ .name = "atmega3290",
+ .llvm_name = "atmega3290",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega3290a = Cpu{
+ .name = "atmega3290a",
+ .llvm_name = "atmega3290a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega3290p = Cpu{
+ .name = "atmega3290p",
+ .llvm_name = "atmega3290p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega3290pa = Cpu{
+ .name = "atmega3290pa",
+ .llvm_name = "atmega3290pa",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega329a = Cpu{
+ .name = "atmega329a",
+ .llvm_name = "atmega329a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega329p = Cpu{
+ .name = "atmega329p",
+ .llvm_name = "atmega329p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega329pa = Cpu{
+ .name = "atmega329pa",
+ .llvm_name = "atmega329pa",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega32a = Cpu{
+ .name = "atmega32a",
+ .llvm_name = "atmega32a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega32c1 = Cpu{
+ .name = "atmega32c1",
+ .llvm_name = "atmega32c1",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega32hvb = Cpu{
+ .name = "atmega32hvb",
+ .llvm_name = "atmega32hvb",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega32hvbrevb = Cpu{
+ .name = "atmega32hvbrevb",
+ .llvm_name = "atmega32hvbrevb",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega32m1 = Cpu{
+ .name = "atmega32m1",
+ .llvm_name = "atmega32m1",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega32u2 = Cpu{
+ .name = "atmega32u2",
+ .llvm_name = "atmega32u2",
+ .features = featureSet(&[_]Feature{
+ .avr35,
+ }),
+ };
+ pub const atmega32u4 = Cpu{
+ .name = "atmega32u4",
+ .llvm_name = "atmega32u4",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega32u6 = Cpu{
+ .name = "atmega32u6",
+ .llvm_name = "atmega32u6",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega406 = Cpu{
+ .name = "atmega406",
+ .llvm_name = "atmega406",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega48 = Cpu{
+ .name = "atmega48",
+ .llvm_name = "atmega48",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const atmega48a = Cpu{
+ .name = "atmega48a",
+ .llvm_name = "atmega48a",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const atmega48p = Cpu{
+ .name = "atmega48p",
+ .llvm_name = "atmega48p",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const atmega48pa = Cpu{
+ .name = "atmega48pa",
+ .llvm_name = "atmega48pa",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const atmega64 = Cpu{
+ .name = "atmega64",
+ .llvm_name = "atmega64",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega640 = Cpu{
+ .name = "atmega640",
+ .llvm_name = "atmega640",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega644 = Cpu{
+ .name = "atmega644",
+ .llvm_name = "atmega644",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega644a = Cpu{
+ .name = "atmega644a",
+ .llvm_name = "atmega644a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega644p = Cpu{
+ .name = "atmega644p",
+ .llvm_name = "atmega644p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega644pa = Cpu{
+ .name = "atmega644pa",
+ .llvm_name = "atmega644pa",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega644rfr2 = Cpu{
+ .name = "atmega644rfr2",
+ .llvm_name = "atmega644rfr2",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega645 = Cpu{
+ .name = "atmega645",
+ .llvm_name = "atmega645",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega6450 = Cpu{
+ .name = "atmega6450",
+ .llvm_name = "atmega6450",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega6450a = Cpu{
+ .name = "atmega6450a",
+ .llvm_name = "atmega6450a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega6450p = Cpu{
+ .name = "atmega6450p",
+ .llvm_name = "atmega6450p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega645a = Cpu{
+ .name = "atmega645a",
+ .llvm_name = "atmega645a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega645p = Cpu{
+ .name = "atmega645p",
+ .llvm_name = "atmega645p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega649 = Cpu{
+ .name = "atmega649",
+ .llvm_name = "atmega649",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega6490 = Cpu{
+ .name = "atmega6490",
+ .llvm_name = "atmega6490",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega6490a = Cpu{
+ .name = "atmega6490a",
+ .llvm_name = "atmega6490a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega6490p = Cpu{
+ .name = "atmega6490p",
+ .llvm_name = "atmega6490p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega649a = Cpu{
+ .name = "atmega649a",
+ .llvm_name = "atmega649a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega649p = Cpu{
+ .name = "atmega649p",
+ .llvm_name = "atmega649p",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega64a = Cpu{
+ .name = "atmega64a",
+ .llvm_name = "atmega64a",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega64c1 = Cpu{
+ .name = "atmega64c1",
+ .llvm_name = "atmega64c1",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega64hve = Cpu{
+ .name = "atmega64hve",
+ .llvm_name = "atmega64hve",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega64m1 = Cpu{
+ .name = "atmega64m1",
+ .llvm_name = "atmega64m1",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega64rfr2 = Cpu{
+ .name = "atmega64rfr2",
+ .llvm_name = "atmega64rfr2",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const atmega8 = Cpu{
+ .name = "atmega8",
+ .llvm_name = "atmega8",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const atmega8515 = Cpu{
+ .name = "atmega8515",
+ .llvm_name = "atmega8515",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ .lpmx,
+ .movw,
+ .mul,
+ .spm,
+ }),
+ };
+ pub const atmega8535 = Cpu{
+ .name = "atmega8535",
+ .llvm_name = "atmega8535",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ .lpmx,
+ .movw,
+ .mul,
+ .spm,
+ }),
+ };
+ pub const atmega88 = Cpu{
+ .name = "atmega88",
+ .llvm_name = "atmega88",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const atmega88a = Cpu{
+ .name = "atmega88a",
+ .llvm_name = "atmega88a",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const atmega88p = Cpu{
+ .name = "atmega88p",
+ .llvm_name = "atmega88p",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const atmega88pa = Cpu{
+ .name = "atmega88pa",
+ .llvm_name = "atmega88pa",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const atmega8a = Cpu{
+ .name = "atmega8a",
+ .llvm_name = "atmega8a",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const atmega8hva = Cpu{
+ .name = "atmega8hva",
+ .llvm_name = "atmega8hva",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const atmega8u2 = Cpu{
+ .name = "atmega8u2",
+ .llvm_name = "atmega8u2",
+ .features = featureSet(&[_]Feature{
+ .avr35,
+ }),
+ };
+ pub const attiny10 = Cpu{
+ .name = "attiny10",
+ .llvm_name = "attiny10",
+ .features = featureSet(&[_]Feature{
+ .avrtiny,
+ }),
+ };
+ pub const attiny102 = Cpu{
+ .name = "attiny102",
+ .llvm_name = "attiny102",
+ .features = featureSet(&[_]Feature{
+ .avrtiny,
+ }),
+ };
+ pub const attiny104 = Cpu{
+ .name = "attiny104",
+ .llvm_name = "attiny104",
+ .features = featureSet(&[_]Feature{
+ .avrtiny,
+ }),
+ };
+ pub const attiny11 = Cpu{
+ .name = "attiny11",
+ .llvm_name = "attiny11",
+ .features = featureSet(&[_]Feature{
+ .avr1,
+ }),
+ };
+ pub const attiny12 = Cpu{
+ .name = "attiny12",
+ .llvm_name = "attiny12",
+ .features = featureSet(&[_]Feature{
+ .avr1,
+ }),
+ };
+ pub const attiny13 = Cpu{
+ .name = "attiny13",
+ .llvm_name = "attiny13",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny13a = Cpu{
+ .name = "attiny13a",
+ .llvm_name = "attiny13a",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny15 = Cpu{
+ .name = "attiny15",
+ .llvm_name = "attiny15",
+ .features = featureSet(&[_]Feature{
+ .avr1,
+ }),
+ };
+ pub const attiny1634 = Cpu{
+ .name = "attiny1634",
+ .llvm_name = "attiny1634",
+ .features = featureSet(&[_]Feature{
+ .avr35,
+ }),
+ };
+ pub const attiny167 = Cpu{
+ .name = "attiny167",
+ .llvm_name = "attiny167",
+ .features = featureSet(&[_]Feature{
+ .avr35,
+ }),
+ };
+ pub const attiny20 = Cpu{
+ .name = "attiny20",
+ .llvm_name = "attiny20",
+ .features = featureSet(&[_]Feature{
+ .avrtiny,
+ }),
+ };
+ pub const attiny22 = Cpu{
+ .name = "attiny22",
+ .llvm_name = "attiny22",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ }),
+ };
+ pub const attiny2313 = Cpu{
+ .name = "attiny2313",
+ .llvm_name = "attiny2313",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny2313a = Cpu{
+ .name = "attiny2313a",
+ .llvm_name = "attiny2313a",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny24 = Cpu{
+ .name = "attiny24",
+ .llvm_name = "attiny24",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny24a = Cpu{
+ .name = "attiny24a",
+ .llvm_name = "attiny24a",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny25 = Cpu{
+ .name = "attiny25",
+ .llvm_name = "attiny25",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny26 = Cpu{
+ .name = "attiny26",
+ .llvm_name = "attiny26",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ .lpmx,
+ }),
+ };
+ pub const attiny261 = Cpu{
+ .name = "attiny261",
+ .llvm_name = "attiny261",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny261a = Cpu{
+ .name = "attiny261a",
+ .llvm_name = "attiny261a",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny28 = Cpu{
+ .name = "attiny28",
+ .llvm_name = "attiny28",
+ .features = featureSet(&[_]Feature{
+ .avr1,
+ }),
+ };
+ pub const attiny4 = Cpu{
+ .name = "attiny4",
+ .llvm_name = "attiny4",
+ .features = featureSet(&[_]Feature{
+ .avrtiny,
+ }),
+ };
+ pub const attiny40 = Cpu{
+ .name = "attiny40",
+ .llvm_name = "attiny40",
+ .features = featureSet(&[_]Feature{
+ .avrtiny,
+ }),
+ };
+ pub const attiny4313 = Cpu{
+ .name = "attiny4313",
+ .llvm_name = "attiny4313",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny43u = Cpu{
+ .name = "attiny43u",
+ .llvm_name = "attiny43u",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny44 = Cpu{
+ .name = "attiny44",
+ .llvm_name = "attiny44",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny44a = Cpu{
+ .name = "attiny44a",
+ .llvm_name = "attiny44a",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny45 = Cpu{
+ .name = "attiny45",
+ .llvm_name = "attiny45",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny461 = Cpu{
+ .name = "attiny461",
+ .llvm_name = "attiny461",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny461a = Cpu{
+ .name = "attiny461a",
+ .llvm_name = "attiny461a",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny48 = Cpu{
+ .name = "attiny48",
+ .llvm_name = "attiny48",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny5 = Cpu{
+ .name = "attiny5",
+ .llvm_name = "attiny5",
+ .features = featureSet(&[_]Feature{
+ .avrtiny,
+ }),
+ };
+ pub const attiny828 = Cpu{
+ .name = "attiny828",
+ .llvm_name = "attiny828",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny84 = Cpu{
+ .name = "attiny84",
+ .llvm_name = "attiny84",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny84a = Cpu{
+ .name = "attiny84a",
+ .llvm_name = "attiny84a",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny85 = Cpu{
+ .name = "attiny85",
+ .llvm_name = "attiny85",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny861 = Cpu{
+ .name = "attiny861",
+ .llvm_name = "attiny861",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny861a = Cpu{
+ .name = "attiny861a",
+ .llvm_name = "attiny861a",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny87 = Cpu{
+ .name = "attiny87",
+ .llvm_name = "attiny87",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny88 = Cpu{
+ .name = "attiny88",
+ .llvm_name = "attiny88",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const attiny9 = Cpu{
+ .name = "attiny9",
+ .llvm_name = "attiny9",
+ .features = featureSet(&[_]Feature{
+ .avrtiny,
+ }),
+ };
+ pub const atxmega128a1 = Cpu{
+ .name = "atxmega128a1",
+ .llvm_name = "atxmega128a1",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega128a1u = Cpu{
+ .name = "atxmega128a1u",
+ .llvm_name = "atxmega128a1u",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega128a3 = Cpu{
+ .name = "atxmega128a3",
+ .llvm_name = "atxmega128a3",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega128a3u = Cpu{
+ .name = "atxmega128a3u",
+ .llvm_name = "atxmega128a3u",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega128a4u = Cpu{
+ .name = "atxmega128a4u",
+ .llvm_name = "atxmega128a4u",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega128b1 = Cpu{
+ .name = "atxmega128b1",
+ .llvm_name = "atxmega128b1",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega128b3 = Cpu{
+ .name = "atxmega128b3",
+ .llvm_name = "atxmega128b3",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega128c3 = Cpu{
+ .name = "atxmega128c3",
+ .llvm_name = "atxmega128c3",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega128d3 = Cpu{
+ .name = "atxmega128d3",
+ .llvm_name = "atxmega128d3",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega128d4 = Cpu{
+ .name = "atxmega128d4",
+ .llvm_name = "atxmega128d4",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega16a4 = Cpu{
+ .name = "atxmega16a4",
+ .llvm_name = "atxmega16a4",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega16a4u = Cpu{
+ .name = "atxmega16a4u",
+ .llvm_name = "atxmega16a4u",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega16c4 = Cpu{
+ .name = "atxmega16c4",
+ .llvm_name = "atxmega16c4",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega16d4 = Cpu{
+ .name = "atxmega16d4",
+ .llvm_name = "atxmega16d4",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega16e5 = Cpu{
+ .name = "atxmega16e5",
+ .llvm_name = "atxmega16e5",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega192a3 = Cpu{
+ .name = "atxmega192a3",
+ .llvm_name = "atxmega192a3",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega192a3u = Cpu{
+ .name = "atxmega192a3u",
+ .llvm_name = "atxmega192a3u",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega192c3 = Cpu{
+ .name = "atxmega192c3",
+ .llvm_name = "atxmega192c3",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega192d3 = Cpu{
+ .name = "atxmega192d3",
+ .llvm_name = "atxmega192d3",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega256a3 = Cpu{
+ .name = "atxmega256a3",
+ .llvm_name = "atxmega256a3",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega256a3b = Cpu{
+ .name = "atxmega256a3b",
+ .llvm_name = "atxmega256a3b",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega256a3bu = Cpu{
+ .name = "atxmega256a3bu",
+ .llvm_name = "atxmega256a3bu",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega256a3u = Cpu{
+ .name = "atxmega256a3u",
+ .llvm_name = "atxmega256a3u",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega256c3 = Cpu{
+ .name = "atxmega256c3",
+ .llvm_name = "atxmega256c3",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega256d3 = Cpu{
+ .name = "atxmega256d3",
+ .llvm_name = "atxmega256d3",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega32a4 = Cpu{
+ .name = "atxmega32a4",
+ .llvm_name = "atxmega32a4",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega32a4u = Cpu{
+ .name = "atxmega32a4u",
+ .llvm_name = "atxmega32a4u",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega32c4 = Cpu{
+ .name = "atxmega32c4",
+ .llvm_name = "atxmega32c4",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega32d4 = Cpu{
+ .name = "atxmega32d4",
+ .llvm_name = "atxmega32d4",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega32e5 = Cpu{
+ .name = "atxmega32e5",
+ .llvm_name = "atxmega32e5",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega32x1 = Cpu{
+ .name = "atxmega32x1",
+ .llvm_name = "atxmega32x1",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega384c3 = Cpu{
+ .name = "atxmega384c3",
+ .llvm_name = "atxmega384c3",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega384d3 = Cpu{
+ .name = "atxmega384d3",
+ .llvm_name = "atxmega384d3",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega64a1 = Cpu{
+ .name = "atxmega64a1",
+ .llvm_name = "atxmega64a1",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega64a1u = Cpu{
+ .name = "atxmega64a1u",
+ .llvm_name = "atxmega64a1u",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega64a3 = Cpu{
+ .name = "atxmega64a3",
+ .llvm_name = "atxmega64a3",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega64a3u = Cpu{
+ .name = "atxmega64a3u",
+ .llvm_name = "atxmega64a3u",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega64a4u = Cpu{
+ .name = "atxmega64a4u",
+ .llvm_name = "atxmega64a4u",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega64b1 = Cpu{
+ .name = "atxmega64b1",
+ .llvm_name = "atxmega64b1",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega64b3 = Cpu{
+ .name = "atxmega64b3",
+ .llvm_name = "atxmega64b3",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega64c3 = Cpu{
+ .name = "atxmega64c3",
+ .llvm_name = "atxmega64c3",
+ .features = featureSet(&[_]Feature{
+ .xmegau,
+ }),
+ };
+ pub const atxmega64d3 = Cpu{
+ .name = "atxmega64d3",
+ .llvm_name = "atxmega64d3",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega64d4 = Cpu{
+ .name = "atxmega64d4",
+ .llvm_name = "atxmega64d4",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const atxmega8e5 = Cpu{
+ .name = "atxmega8e5",
+ .llvm_name = "atxmega8e5",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const avr1 = Cpu{
+ .name = "avr1",
+ .llvm_name = "avr1",
+ .features = featureSet(&[_]Feature{
+ .avr1,
+ }),
+ };
+ pub const avr2 = Cpu{
+ .name = "avr2",
+ .llvm_name = "avr2",
+ .features = featureSet(&[_]Feature{
+ .avr2,
+ }),
+ };
+ pub const avr25 = Cpu{
+ .name = "avr25",
+ .llvm_name = "avr25",
+ .features = featureSet(&[_]Feature{
+ .avr25,
+ }),
+ };
+ pub const avr3 = Cpu{
+ .name = "avr3",
+ .llvm_name = "avr3",
+ .features = featureSet(&[_]Feature{
+ .avr3,
+ }),
+ };
+ pub const avr31 = Cpu{
+ .name = "avr31",
+ .llvm_name = "avr31",
+ .features = featureSet(&[_]Feature{
+ .avr31,
+ }),
+ };
+ pub const avr35 = Cpu{
+ .name = "avr35",
+ .llvm_name = "avr35",
+ .features = featureSet(&[_]Feature{
+ .avr35,
+ }),
+ };
+ pub const avr4 = Cpu{
+ .name = "avr4",
+ .llvm_name = "avr4",
+ .features = featureSet(&[_]Feature{
+ .avr4,
+ }),
+ };
+ pub const avr5 = Cpu{
+ .name = "avr5",
+ .llvm_name = "avr5",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+ pub const avr51 = Cpu{
+ .name = "avr51",
+ .llvm_name = "avr51",
+ .features = featureSet(&[_]Feature{
+ .avr51,
+ }),
+ };
+ pub const avr6 = Cpu{
+ .name = "avr6",
+ .llvm_name = "avr6",
+ .features = featureSet(&[_]Feature{
+ .avr6,
+ }),
+ };
+ pub const avrtiny = Cpu{
+ .name = "avrtiny",
+ .llvm_name = "avrtiny",
+ .features = featureSet(&[_]Feature{
+ .avrtiny,
+ }),
+ };
+ pub const avrxmega1 = Cpu{
+ .name = "avrxmega1",
+ .llvm_name = "avrxmega1",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const avrxmega2 = Cpu{
+ .name = "avrxmega2",
+ .llvm_name = "avrxmega2",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const avrxmega3 = Cpu{
+ .name = "avrxmega3",
+ .llvm_name = "avrxmega3",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const avrxmega4 = Cpu{
+ .name = "avrxmega4",
+ .llvm_name = "avrxmega4",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const avrxmega5 = Cpu{
+ .name = "avrxmega5",
+ .llvm_name = "avrxmega5",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const avrxmega6 = Cpu{
+ .name = "avrxmega6",
+ .llvm_name = "avrxmega6",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const avrxmega7 = Cpu{
+ .name = "avrxmega7",
+ .llvm_name = "avrxmega7",
+ .features = featureSet(&[_]Feature{
+ .xmega,
+ }),
+ };
+ pub const m3000 = Cpu{
+ .name = "m3000",
+ .llvm_name = "m3000",
+ .features = featureSet(&[_]Feature{
+ .avr5,
+ }),
+ };
+};
+
+/// All avr 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.at43usb320,
+ &cpu.at43usb355,
+ &cpu.at76c711,
+ &cpu.at86rf401,
+ &cpu.at90c8534,
+ &cpu.at90can128,
+ &cpu.at90can32,
+ &cpu.at90can64,
+ &cpu.at90pwm1,
+ &cpu.at90pwm161,
+ &cpu.at90pwm2,
+ &cpu.at90pwm216,
+ &cpu.at90pwm2b,
+ &cpu.at90pwm3,
+ &cpu.at90pwm316,
+ &cpu.at90pwm3b,
+ &cpu.at90pwm81,
+ &cpu.at90s1200,
+ &cpu.at90s2313,
+ &cpu.at90s2323,
+ &cpu.at90s2333,
+ &cpu.at90s2343,
+ &cpu.at90s4414,
+ &cpu.at90s4433,
+ &cpu.at90s4434,
+ &cpu.at90s8515,
+ &cpu.at90s8535,
+ &cpu.at90scr100,
+ &cpu.at90usb1286,
+ &cpu.at90usb1287,
+ &cpu.at90usb162,
+ &cpu.at90usb646,
+ &cpu.at90usb647,
+ &cpu.at90usb82,
+ &cpu.at94k,
+ &cpu.ata5272,
+ &cpu.ata5505,
+ &cpu.ata5790,
+ &cpu.ata5795,
+ &cpu.ata6285,
+ &cpu.ata6286,
+ &cpu.ata6289,
+ &cpu.atmega103,
+ &cpu.atmega128,
+ &cpu.atmega1280,
+ &cpu.atmega1281,
+ &cpu.atmega1284,
+ &cpu.atmega1284p,
+ &cpu.atmega1284rfr2,
+ &cpu.atmega128a,
+ &cpu.atmega128rfa1,
+ &cpu.atmega128rfr2,
+ &cpu.atmega16,
+ &cpu.atmega161,
+ &cpu.atmega162,
+ &cpu.atmega163,
+ &cpu.atmega164a,
+ &cpu.atmega164p,
+ &cpu.atmega164pa,
+ &cpu.atmega165,
+ &cpu.atmega165a,
+ &cpu.atmega165p,
+ &cpu.atmega165pa,
+ &cpu.atmega168,
+ &cpu.atmega168a,
+ &cpu.atmega168p,
+ &cpu.atmega168pa,
+ &cpu.atmega169,
+ &cpu.atmega169a,
+ &cpu.atmega169p,
+ &cpu.atmega169pa,
+ &cpu.atmega16a,
+ &cpu.atmega16hva,
+ &cpu.atmega16hva2,
+ &cpu.atmega16hvb,
+ &cpu.atmega16hvbrevb,
+ &cpu.atmega16m1,
+ &cpu.atmega16u2,
+ &cpu.atmega16u4,
+ &cpu.atmega2560,
+ &cpu.atmega2561,
+ &cpu.atmega2564rfr2,
+ &cpu.atmega256rfr2,
+ &cpu.atmega32,
+ &cpu.atmega323,
+ &cpu.atmega324a,
+ &cpu.atmega324p,
+ &cpu.atmega324pa,
+ &cpu.atmega325,
+ &cpu.atmega3250,
+ &cpu.atmega3250a,
+ &cpu.atmega3250p,
+ &cpu.atmega3250pa,
+ &cpu.atmega325a,
+ &cpu.atmega325p,
+ &cpu.atmega325pa,
+ &cpu.atmega328,
+ &cpu.atmega328p,
+ &cpu.atmega329,
+ &cpu.atmega3290,
+ &cpu.atmega3290a,
+ &cpu.atmega3290p,
+ &cpu.atmega3290pa,
+ &cpu.atmega329a,
+ &cpu.atmega329p,
+ &cpu.atmega329pa,
+ &cpu.atmega32a,
+ &cpu.atmega32c1,
+ &cpu.atmega32hvb,
+ &cpu.atmega32hvbrevb,
+ &cpu.atmega32m1,
+ &cpu.atmega32u2,
+ &cpu.atmega32u4,
+ &cpu.atmega32u6,
+ &cpu.atmega406,
+ &cpu.atmega48,
+ &cpu.atmega48a,
+ &cpu.atmega48p,
+ &cpu.atmega48pa,
+ &cpu.atmega64,
+ &cpu.atmega640,
+ &cpu.atmega644,
+ &cpu.atmega644a,
+ &cpu.atmega644p,
+ &cpu.atmega644pa,
+ &cpu.atmega644rfr2,
+ &cpu.atmega645,
+ &cpu.atmega6450,
+ &cpu.atmega6450a,
+ &cpu.atmega6450p,
+ &cpu.atmega645a,
+ &cpu.atmega645p,
+ &cpu.atmega649,
+ &cpu.atmega6490,
+ &cpu.atmega6490a,
+ &cpu.atmega6490p,
+ &cpu.atmega649a,
+ &cpu.atmega649p,
+ &cpu.atmega64a,
+ &cpu.atmega64c1,
+ &cpu.atmega64hve,
+ &cpu.atmega64m1,
+ &cpu.atmega64rfr2,
+ &cpu.atmega8,
+ &cpu.atmega8515,
+ &cpu.atmega8535,
+ &cpu.atmega88,
+ &cpu.atmega88a,
+ &cpu.atmega88p,
+ &cpu.atmega88pa,
+ &cpu.atmega8a,
+ &cpu.atmega8hva,
+ &cpu.atmega8u2,
+ &cpu.attiny10,
+ &cpu.attiny102,
+ &cpu.attiny104,
+ &cpu.attiny11,
+ &cpu.attiny12,
+ &cpu.attiny13,
+ &cpu.attiny13a,
+ &cpu.attiny15,
+ &cpu.attiny1634,
+ &cpu.attiny167,
+ &cpu.attiny20,
+ &cpu.attiny22,
+ &cpu.attiny2313,
+ &cpu.attiny2313a,
+ &cpu.attiny24,
+ &cpu.attiny24a,
+ &cpu.attiny25,
+ &cpu.attiny26,
+ &cpu.attiny261,
+ &cpu.attiny261a,
+ &cpu.attiny28,
+ &cpu.attiny4,
+ &cpu.attiny40,
+ &cpu.attiny4313,
+ &cpu.attiny43u,
+ &cpu.attiny44,
+ &cpu.attiny44a,
+ &cpu.attiny45,
+ &cpu.attiny461,
+ &cpu.attiny461a,
+ &cpu.attiny48,
+ &cpu.attiny5,
+ &cpu.attiny828,
+ &cpu.attiny84,
+ &cpu.attiny84a,
+ &cpu.attiny85,
+ &cpu.attiny861,
+ &cpu.attiny861a,
+ &cpu.attiny87,
+ &cpu.attiny88,
+ &cpu.attiny9,
+ &cpu.atxmega128a1,
+ &cpu.atxmega128a1u,
+ &cpu.atxmega128a3,
+ &cpu.atxmega128a3u,
+ &cpu.atxmega128a4u,
+ &cpu.atxmega128b1,
+ &cpu.atxmega128b3,
+ &cpu.atxmega128c3,
+ &cpu.atxmega128d3,
+ &cpu.atxmega128d4,
+ &cpu.atxmega16a4,
+ &cpu.atxmega16a4u,
+ &cpu.atxmega16c4,
+ &cpu.atxmega16d4,
+ &cpu.atxmega16e5,
+ &cpu.atxmega192a3,
+ &cpu.atxmega192a3u,
+ &cpu.atxmega192c3,
+ &cpu.atxmega192d3,
+ &cpu.atxmega256a3,
+ &cpu.atxmega256a3b,
+ &cpu.atxmega256a3bu,
+ &cpu.atxmega256a3u,
+ &cpu.atxmega256c3,
+ &cpu.atxmega256d3,
+ &cpu.atxmega32a4,
+ &cpu.atxmega32a4u,
+ &cpu.atxmega32c4,
+ &cpu.atxmega32d4,
+ &cpu.atxmega32e5,
+ &cpu.atxmega32x1,
+ &cpu.atxmega384c3,
+ &cpu.atxmega384d3,
+ &cpu.atxmega64a1,
+ &cpu.atxmega64a1u,
+ &cpu.atxmega64a3,
+ &cpu.atxmega64a3u,
+ &cpu.atxmega64a4u,
+ &cpu.atxmega64b1,
+ &cpu.atxmega64b3,
+ &cpu.atxmega64c3,
+ &cpu.atxmega64d3,
+ &cpu.atxmega64d4,
+ &cpu.atxmega8e5,
+ &cpu.avr1,
+ &cpu.avr2,
+ &cpu.avr25,
+ &cpu.avr3,
+ &cpu.avr31,
+ &cpu.avr35,
+ &cpu.avr4,
+ &cpu.avr5,
+ &cpu.avr51,
+ &cpu.avr6,
+ &cpu.avrtiny,
+ &cpu.avrxmega1,
+ &cpu.avrxmega2,
+ &cpu.avrxmega3,
+ &cpu.avrxmega4,
+ &cpu.avrxmega5,
+ &cpu.avrxmega6,
+ &cpu.avrxmega7,
+ &cpu.m3000,
+};
diff --git a/lib/std/target/bpf.zig b/lib/std/target/bpf.zig
new file mode 100644
index 0000000000..b6179075cc
--- /dev/null
+++ b/lib/std/target/bpf.zig
@@ -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,
+};
diff --git a/lib/std/target/hexagon.zig b/lib/std/target/hexagon.zig
new file mode 100644
index 0000000000..f873237493
--- /dev/null
+++ b/lib/std/target/hexagon.zig
@@ -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,
+};
diff --git a/lib/std/target/mips.zig b/lib/std/target/mips.zig
new file mode 100644
index 0000000000..fce7c9ce36
--- /dev/null
+++ b/lib/std/target/mips.zig
@@ -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,
+};
diff --git a/lib/std/target/msp430.zig b/lib/std/target/msp430.zig
new file mode 100644
index 0000000000..bc932f2295
--- /dev/null
+++ b/lib/std/target/msp430.zig
@@ -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,
+};
diff --git a/lib/std/target/nvptx.zig b/lib/std/target/nvptx.zig
new file mode 100644
index 0000000000..1800e320b4
--- /dev/null
+++ b/lib/std/target/nvptx.zig
@@ -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,
+};
diff --git a/lib/std/target/powerpc.zig b/lib/std/target/powerpc.zig
new file mode 100644
index 0000000000..41321f7b04
--- /dev/null
+++ b/lib/std/target/powerpc.zig
@@ -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,
+};
diff --git a/lib/std/target/riscv.zig b/lib/std/target/riscv.zig
new file mode 100644
index 0000000000..315329306e
--- /dev/null
+++ b/lib/std/target/riscv.zig
@@ -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,
+};
diff --git a/lib/std/target/sparc.zig b/lib/std/target/sparc.zig
new file mode 100644
index 0000000000..923cc0732c
--- /dev/null
+++ b/lib/std/target/sparc.zig
@@ -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,
+};
diff --git a/lib/std/target/systemz.zig b/lib/std/target/systemz.zig
new file mode 100644
index 0000000000..c924af6e70
--- /dev/null
+++ b/lib/std/target/systemz.zig
@@ -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,
+};
diff --git a/lib/std/target/wasm.zig b/lib/std/target/wasm.zig
new file mode 100644
index 0000000000..6d79bbb282
--- /dev/null
+++ b/lib/std/target/wasm.zig
@@ -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,
+};
diff --git a/lib/std/target/x86.zig b/lib/std/target/x86.zig
new file mode 100644
index 0000000000..3c2e306e79
--- /dev/null
+++ b/lib/std/target/x86.zig
@@ -0,0 +1,2859 @@
+const std = @import("../std.zig");
+const Cpu = std.Target.Cpu;
+
+pub const Feature = enum {
+ @"3dnow",
+ @"3dnowa",
+ @"64bit",
+ adx,
+ aes,
+ avx,
+ avx2,
+ avx512bf16,
+ avx512bitalg,
+ avx512bw,
+ avx512cd,
+ avx512dq,
+ avx512er,
+ avx512f,
+ avx512ifma,
+ avx512pf,
+ avx512vbmi,
+ avx512vbmi2,
+ avx512vl,
+ avx512vnni,
+ avx512vp2intersect,
+ avx512vpopcntdq,
+ bmi,
+ bmi2,
+ branchfusion,
+ cldemote,
+ clflushopt,
+ clwb,
+ clzero,
+ cmov,
+ cx16,
+ cx8,
+ enqcmd,
+ ermsb,
+ f16c,
+ false_deps_lzcnt_tzcnt,
+ false_deps_popcnt,
+ fast_11bytenop,
+ fast_15bytenop,
+ fast_bextr,
+ fast_gather,
+ fast_hops,
+ fast_lzcnt,
+ fast_partial_ymm_or_zmm_write,
+ fast_scalar_fsqrt,
+ fast_scalar_shift_masks,
+ fast_shld_rotate,
+ fast_variable_shuffle,
+ fast_vector_fsqrt,
+ fast_vector_shift_masks,
+ fma,
+ fma4,
+ fsgsbase,
+ fxsr,
+ gfni,
+ idivl_to_divb,
+ idivq_to_divl,
+ invpcid,
+ lea_sp,
+ lea_uses_ag,
+ lwp,
+ lzcnt,
+ macrofusion,
+ merge_to_threeway_branch,
+ mmx,
+ movbe,
+ movdir64b,
+ movdiri,
+ mpx,
+ mwaitx,
+ nopl,
+ pad_short_functions,
+ pclmul,
+ pconfig,
+ pku,
+ popcnt,
+ prefer_256_bit,
+ prefetchwt1,
+ prfchw,
+ ptwrite,
+ rdpid,
+ rdrnd,
+ rdseed,
+ retpoline,
+ retpoline_external_thunk,
+ retpoline_indirect_branches,
+ retpoline_indirect_calls,
+ rtm,
+ sahf,
+ sgx,
+ sha,
+ shstk,
+ slow_3ops_lea,
+ slow_incdec,
+ slow_lea,
+ slow_pmaddwd,
+ slow_pmulld,
+ slow_shld,
+ slow_two_mem_ops,
+ slow_unaligned_mem_16,
+ slow_unaligned_mem_32,
+ soft_float,
+ sse,
+ sse_unaligned_mem,
+ sse2,
+ sse3,
+ sse4_1,
+ sse4_2,
+ sse4a,
+ ssse3,
+ tbm,
+ vaes,
+ vpclmulqdq,
+ waitpkg,
+ wbnoinvd,
+ x87,
+ xop,
+ xsave,
+ xsavec,
+ xsaveopt,
+ xsaves,
+};
+
+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.@"3dnow")] = .{
+ .llvm_name = "3dnow",
+ .description = "Enable 3DNow! instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .mmx,
+ }),
+ };
+ result[@enumToInt(Feature.@"3dnowa")] = .{
+ .llvm_name = "3dnowa",
+ .description = "Enable 3DNow! Athlon instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .@"3dnow",
+ }),
+ };
+ result[@enumToInt(Feature.@"64bit")] = .{
+ .llvm_name = "64bit",
+ .description = "Support 64-bit instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.adx)] = .{
+ .llvm_name = "adx",
+ .description = "Support ADX instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.aes)] = .{
+ .llvm_name = "aes",
+ .description = "Enable AES instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sse2,
+ }),
+ };
+ result[@enumToInt(Feature.avx)] = .{
+ .llvm_name = "avx",
+ .description = "Enable AVX instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sse4_2,
+ }),
+ };
+ result[@enumToInt(Feature.avx2)] = .{
+ .llvm_name = "avx2",
+ .description = "Enable AVX2 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx,
+ }),
+ };
+ result[@enumToInt(Feature.avx512bf16)] = .{
+ .llvm_name = "avx512bf16",
+ .description = "Support bfloat16 floating point",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512bw,
+ }),
+ };
+ result[@enumToInt(Feature.avx512bitalg)] = .{
+ .llvm_name = "avx512bitalg",
+ .description = "Enable AVX-512 Bit Algorithms",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512bw,
+ }),
+ };
+ result[@enumToInt(Feature.avx512bw)] = .{
+ .llvm_name = "avx512bw",
+ .description = "Enable AVX-512 Byte and Word Instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512f,
+ }),
+ };
+ result[@enumToInt(Feature.avx512cd)] = .{
+ .llvm_name = "avx512cd",
+ .description = "Enable AVX-512 Conflict Detection Instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512f,
+ }),
+ };
+ result[@enumToInt(Feature.avx512dq)] = .{
+ .llvm_name = "avx512dq",
+ .description = "Enable AVX-512 Doubleword and Quadword Instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512f,
+ }),
+ };
+ result[@enumToInt(Feature.avx512er)] = .{
+ .llvm_name = "avx512er",
+ .description = "Enable AVX-512 Exponential and Reciprocal Instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512f,
+ }),
+ };
+ result[@enumToInt(Feature.avx512f)] = .{
+ .llvm_name = "avx512f",
+ .description = "Enable AVX-512 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx2,
+ .f16c,
+ .fma,
+ }),
+ };
+ result[@enumToInt(Feature.avx512ifma)] = .{
+ .llvm_name = "avx512ifma",
+ .description = "Enable AVX-512 Integer Fused Multiple-Add",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512f,
+ }),
+ };
+ result[@enumToInt(Feature.avx512pf)] = .{
+ .llvm_name = "avx512pf",
+ .description = "Enable AVX-512 PreFetch Instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512f,
+ }),
+ };
+ result[@enumToInt(Feature.avx512vbmi)] = .{
+ .llvm_name = "avx512vbmi",
+ .description = "Enable AVX-512 Vector Byte Manipulation Instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512bw,
+ }),
+ };
+ result[@enumToInt(Feature.avx512vbmi2)] = .{
+ .llvm_name = "avx512vbmi2",
+ .description = "Enable AVX-512 further Vector Byte Manipulation Instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512bw,
+ }),
+ };
+ result[@enumToInt(Feature.avx512vl)] = .{
+ .llvm_name = "avx512vl",
+ .description = "Enable AVX-512 Vector Length eXtensions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512f,
+ }),
+ };
+ result[@enumToInt(Feature.avx512vnni)] = .{
+ .llvm_name = "avx512vnni",
+ .description = "Enable AVX-512 Vector Neural Network Instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512f,
+ }),
+ };
+ result[@enumToInt(Feature.avx512vp2intersect)] = .{
+ .llvm_name = "avx512vp2intersect",
+ .description = "Enable AVX-512 vp2intersect",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512f,
+ }),
+ };
+ result[@enumToInt(Feature.avx512vpopcntdq)] = .{
+ .llvm_name = "avx512vpopcntdq",
+ .description = "Enable AVX-512 Population Count Instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx512f,
+ }),
+ };
+ result[@enumToInt(Feature.bmi)] = .{
+ .llvm_name = "bmi",
+ .description = "Support BMI instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.bmi2)] = .{
+ .llvm_name = "bmi2",
+ .description = "Support BMI2 instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.branchfusion)] = .{
+ .llvm_name = "branchfusion",
+ .description = "CMP/TEST can be fused with conditional branches",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.cldemote)] = .{
+ .llvm_name = "cldemote",
+ .description = "Enable Cache Demote",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.clflushopt)] = .{
+ .llvm_name = "clflushopt",
+ .description = "Flush A Cache Line Optimized",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.clwb)] = .{
+ .llvm_name = "clwb",
+ .description = "Cache Line Write Back",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.clzero)] = .{
+ .llvm_name = "clzero",
+ .description = "Enable Cache Line Zero",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.cmov)] = .{
+ .llvm_name = "cmov",
+ .description = "Enable conditional move instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.cx16)] = .{
+ .llvm_name = "cx16",
+ .description = "64-bit with cmpxchg16b",
+ .dependencies = featureSet(&[_]Feature{
+ .cx8,
+ }),
+ };
+ result[@enumToInt(Feature.cx8)] = .{
+ .llvm_name = "cx8",
+ .description = "Support CMPXCHG8B instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.enqcmd)] = .{
+ .llvm_name = "enqcmd",
+ .description = "Has ENQCMD instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ermsb)] = .{
+ .llvm_name = "ermsb",
+ .description = "REP MOVS/STOS are fast",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.f16c)] = .{
+ .llvm_name = "f16c",
+ .description = "Support 16-bit floating point conversion instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx,
+ }),
+ };
+ result[@enumToInt(Feature.false_deps_lzcnt_tzcnt)] = .{
+ .llvm_name = "false-deps-lzcnt-tzcnt",
+ .description = "LZCNT/TZCNT have a false dependency on dest register",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.false_deps_popcnt)] = .{
+ .llvm_name = "false-deps-popcnt",
+ .description = "POPCNT has a false dependency on dest register",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_11bytenop)] = .{
+ .llvm_name = "fast-11bytenop",
+ .description = "Target can quickly decode up to 11 byte NOPs",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_15bytenop)] = .{
+ .llvm_name = "fast-15bytenop",
+ .description = "Target can quickly decode up to 15 byte NOPs",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_bextr)] = .{
+ .llvm_name = "fast-bextr",
+ .description = "Indicates that the BEXTR instruction is implemented as a single uop with good throughput",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_gather)] = .{
+ .llvm_name = "fast-gather",
+ .description = "Indicates if gather is reasonably fast",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_hops)] = .{
+ .llvm_name = "fast-hops",
+ .description = "Prefer horizontal vector math instructions (haddp, phsub, etc.) over normal vector instructions with shuffles",
+ .dependencies = featureSet(&[_]Feature{
+ .sse3,
+ }),
+ };
+ result[@enumToInt(Feature.fast_lzcnt)] = .{
+ .llvm_name = "fast-lzcnt",
+ .description = "LZCNT instructions are as fast as most simple integer ops",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_partial_ymm_or_zmm_write)] = .{
+ .llvm_name = "fast-partial-ymm-or-zmm-write",
+ .description = "Partial writes to YMM/ZMM registers are fast",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_scalar_fsqrt)] = .{
+ .llvm_name = "fast-scalar-fsqrt",
+ .description = "Scalar SQRT is fast (disable Newton-Raphson)",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_scalar_shift_masks)] = .{
+ .llvm_name = "fast-scalar-shift-masks",
+ .description = "Prefer a left/right scalar logical shift pair over a shift+and pair",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_shld_rotate)] = .{
+ .llvm_name = "fast-shld-rotate",
+ .description = "SHLD can be used as a faster rotate",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_variable_shuffle)] = .{
+ .llvm_name = "fast-variable-shuffle",
+ .description = "Shuffles with variable masks are fast",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_vector_fsqrt)] = .{
+ .llvm_name = "fast-vector-fsqrt",
+ .description = "Vector SQRT is fast (disable Newton-Raphson)",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fast_vector_shift_masks)] = .{
+ .llvm_name = "fast-vector-shift-masks",
+ .description = "Prefer a left/right vector logical shift pair over a shift+and pair",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fma)] = .{
+ .llvm_name = "fma",
+ .description = "Enable three-operand fused multiple-add",
+ .dependencies = featureSet(&[_]Feature{
+ .avx,
+ }),
+ };
+ result[@enumToInt(Feature.fma4)] = .{
+ .llvm_name = "fma4",
+ .description = "Enable four-operand fused multiple-add",
+ .dependencies = featureSet(&[_]Feature{
+ .avx,
+ .sse4a,
+ }),
+ };
+ result[@enumToInt(Feature.fsgsbase)] = .{
+ .llvm_name = "fsgsbase",
+ .description = "Support FS/GS Base instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.fxsr)] = .{
+ .llvm_name = "fxsr",
+ .description = "Support fxsave/fxrestore instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.gfni)] = .{
+ .llvm_name = "gfni",
+ .description = "Enable Galois Field Arithmetic Instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sse2,
+ }),
+ };
+ result[@enumToInt(Feature.idivl_to_divb)] = .{
+ .llvm_name = "idivl-to-divb",
+ .description = "Use 8-bit divide for positive values less than 256",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.idivq_to_divl)] = .{
+ .llvm_name = "idivq-to-divl",
+ .description = "Use 32-bit divide for positive values less than 2^32",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.invpcid)] = .{
+ .llvm_name = "invpcid",
+ .description = "Invalidate Process-Context Identifier",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.lea_sp)] = .{
+ .llvm_name = "lea-sp",
+ .description = "Use LEA for adjusting the stack pointer",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.lea_uses_ag)] = .{
+ .llvm_name = "lea-uses-ag",
+ .description = "LEA instruction needs inputs at AG stage",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.lwp)] = .{
+ .llvm_name = "lwp",
+ .description = "Enable LWP instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.lzcnt)] = .{
+ .llvm_name = "lzcnt",
+ .description = "Support LZCNT instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.macrofusion)] = .{
+ .llvm_name = "macrofusion",
+ .description = "Various instructions can be fused with conditional branches",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.merge_to_threeway_branch)] = .{
+ .llvm_name = "merge-to-threeway-branch",
+ .description = "Merge branches to a three-way conditional branch",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.mmx)] = .{
+ .llvm_name = "mmx",
+ .description = "Enable MMX instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.movbe)] = .{
+ .llvm_name = "movbe",
+ .description = "Support MOVBE instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.movdir64b)] = .{
+ .llvm_name = "movdir64b",
+ .description = "Support movdir64b instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.movdiri)] = .{
+ .llvm_name = "movdiri",
+ .description = "Support movdiri instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.mpx)] = .{
+ .llvm_name = "mpx",
+ .description = "Support MPX instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.mwaitx)] = .{
+ .llvm_name = "mwaitx",
+ .description = "Enable MONITORX/MWAITX timer functionality",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.nopl)] = .{
+ .llvm_name = "nopl",
+ .description = "Enable NOPL instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.pad_short_functions)] = .{
+ .llvm_name = "pad-short-functions",
+ .description = "Pad short functions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.pclmul)] = .{
+ .llvm_name = "pclmul",
+ .description = "Enable packed carry-less multiplication instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sse2,
+ }),
+ };
+ result[@enumToInt(Feature.pconfig)] = .{
+ .llvm_name = "pconfig",
+ .description = "platform configuration instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.pku)] = .{
+ .llvm_name = "pku",
+ .description = "Enable protection keys",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.popcnt)] = .{
+ .llvm_name = "popcnt",
+ .description = "Support POPCNT instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.prefer_256_bit)] = .{
+ .llvm_name = "prefer-256-bit",
+ .description = "Prefer 256-bit AVX instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.prefetchwt1)] = .{
+ .llvm_name = "prefetchwt1",
+ .description = "Prefetch with Intent to Write and T1 Hint",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.prfchw)] = .{
+ .llvm_name = "prfchw",
+ .description = "Support PRFCHW instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.ptwrite)] = .{
+ .llvm_name = "ptwrite",
+ .description = "Support ptwrite instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.rdpid)] = .{
+ .llvm_name = "rdpid",
+ .description = "Support RDPID instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.rdrnd)] = .{
+ .llvm_name = "rdrnd",
+ .description = "Support RDRAND instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.rdseed)] = .{
+ .llvm_name = "rdseed",
+ .description = "Support RDSEED instruction",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.retpoline)] = .{
+ .llvm_name = "retpoline",
+ .description = "Remove speculation of indirect branches from the generated code, either by avoiding them entirely or lowering them with a speculation blocking construct",
+ .dependencies = featureSet(&[_]Feature{
+ .retpoline_indirect_branches,
+ .retpoline_indirect_calls,
+ }),
+ };
+ result[@enumToInt(Feature.retpoline_external_thunk)] = .{
+ .llvm_name = "retpoline-external-thunk",
+ .description = "When lowering an indirect call or branch using a `retpoline`, rely on the specified user provided thunk rather than emitting one ourselves. Only has effect when combined with some other retpoline feature",
+ .dependencies = featureSet(&[_]Feature{
+ .retpoline_indirect_calls,
+ }),
+ };
+ result[@enumToInt(Feature.retpoline_indirect_branches)] = .{
+ .llvm_name = "retpoline-indirect-branches",
+ .description = "Remove speculation of indirect branches from the generated code",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.retpoline_indirect_calls)] = .{
+ .llvm_name = "retpoline-indirect-calls",
+ .description = "Remove speculation of indirect calls from the generated code",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.rtm)] = .{
+ .llvm_name = "rtm",
+ .description = "Support RTM instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sahf)] = .{
+ .llvm_name = "sahf",
+ .description = "Support LAHF and SAHF instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sgx)] = .{
+ .llvm_name = "sgx",
+ .description = "Enable Software Guard Extensions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sha)] = .{
+ .llvm_name = "sha",
+ .description = "Enable SHA instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sse2,
+ }),
+ };
+ result[@enumToInt(Feature.shstk)] = .{
+ .llvm_name = "shstk",
+ .description = "Support CET Shadow-Stack instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_3ops_lea)] = .{
+ .llvm_name = "slow-3ops-lea",
+ .description = "LEA instruction with 3 ops or certain registers is slow",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_incdec)] = .{
+ .llvm_name = "slow-incdec",
+ .description = "INC and DEC instructions are slower than ADD and SUB",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_lea)] = .{
+ .llvm_name = "slow-lea",
+ .description = "LEA instruction with certain arguments is slow",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_pmaddwd)] = .{
+ .llvm_name = "slow-pmaddwd",
+ .description = "PMADDWD is slower than PMULLD",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_pmulld)] = .{
+ .llvm_name = "slow-pmulld",
+ .description = "PMULLD instruction is slow",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_shld)] = .{
+ .llvm_name = "slow-shld",
+ .description = "SHLD instruction is slow",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_two_mem_ops)] = .{
+ .llvm_name = "slow-two-mem-ops",
+ .description = "Two memory operand instructions are slow",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_unaligned_mem_16)] = .{
+ .llvm_name = "slow-unaligned-mem-16",
+ .description = "Slow unaligned 16-byte memory access",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.slow_unaligned_mem_32)] = .{
+ .llvm_name = "slow-unaligned-mem-32",
+ .description = "Slow unaligned 32-byte memory access",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.soft_float)] = .{
+ .llvm_name = "soft-float",
+ .description = "Use software floating point features",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sse)] = .{
+ .llvm_name = "sse",
+ .description = "Enable SSE instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sse_unaligned_mem)] = .{
+ .llvm_name = "sse-unaligned-mem",
+ .description = "Allow unaligned memory operands with SSE instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.sse2)] = .{
+ .llvm_name = "sse2",
+ .description = "Enable SSE2 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sse,
+ }),
+ };
+ result[@enumToInt(Feature.sse3)] = .{
+ .llvm_name = "sse3",
+ .description = "Enable SSE3 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sse2,
+ }),
+ };
+ result[@enumToInt(Feature.sse4_1)] = .{
+ .llvm_name = "sse4.1",
+ .description = "Enable SSE 4.1 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .ssse3,
+ }),
+ };
+ result[@enumToInt(Feature.sse4_2)] = .{
+ .llvm_name = "sse4.2",
+ .description = "Enable SSE 4.2 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sse4_1,
+ }),
+ };
+ result[@enumToInt(Feature.sse4a)] = .{
+ .llvm_name = "sse4a",
+ .description = "Support SSE 4a instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sse3,
+ }),
+ };
+ result[@enumToInt(Feature.ssse3)] = .{
+ .llvm_name = "ssse3",
+ .description = "Enable SSSE3 instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .sse3,
+ }),
+ };
+ result[@enumToInt(Feature.tbm)] = .{
+ .llvm_name = "tbm",
+ .description = "Enable TBM instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.vaes)] = .{
+ .llvm_name = "vaes",
+ .description = "Promote selected AES instructions to AVX512/AVX registers",
+ .dependencies = featureSet(&[_]Feature{
+ .aes,
+ .avx,
+ }),
+ };
+ result[@enumToInt(Feature.vpclmulqdq)] = .{
+ .llvm_name = "vpclmulqdq",
+ .description = "Enable vpclmulqdq instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .avx,
+ .pclmul,
+ }),
+ };
+ result[@enumToInt(Feature.waitpkg)] = .{
+ .llvm_name = "waitpkg",
+ .description = "Wait and pause enhancements",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.wbnoinvd)] = .{
+ .llvm_name = "wbnoinvd",
+ .description = "Write Back No Invalidate",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.x87)] = .{
+ .llvm_name = "x87",
+ .description = "Enable X87 float instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.xop)] = .{
+ .llvm_name = "xop",
+ .description = "Enable XOP instructions",
+ .dependencies = featureSet(&[_]Feature{
+ .fma4,
+ }),
+ };
+ result[@enumToInt(Feature.xsave)] = .{
+ .llvm_name = "xsave",
+ .description = "Support xsave instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.xsavec)] = .{
+ .llvm_name = "xsavec",
+ .description = "Support xsavec instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.xsaveopt)] = .{
+ .llvm_name = "xsaveopt",
+ .description = "Support xsaveopt instructions",
+ .dependencies = featureSet(&[_]Feature{}),
+ };
+ result[@enumToInt(Feature.xsaves)] = .{
+ .llvm_name = "xsaves",
+ .description = "Support xsaves 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 amdfam10 = Cpu{
+ .name = "amdfam10",
+ .llvm_name = "amdfam10",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fast_scalar_shift_masks,
+ .fxsr,
+ .lzcnt,
+ .nopl,
+ .popcnt,
+ .sahf,
+ .slow_shld,
+ .sse4a,
+ .x87,
+ }),
+ };
+ pub const athlon = Cpu{
+ .name = "athlon",
+ .llvm_name = "athlon",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .cmov,
+ .cx8,
+ .nopl,
+ .slow_shld,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const athlon_4 = Cpu{
+ .name = "athlon_4",
+ .llvm_name = "athlon-4",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .cmov,
+ .cx8,
+ .fxsr,
+ .nopl,
+ .slow_shld,
+ .slow_unaligned_mem_16,
+ .sse,
+ .x87,
+ }),
+ };
+ pub const athlon_fx = Cpu{
+ .name = "athlon_fx",
+ .llvm_name = "athlon-fx",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .@"64bit",
+ .cmov,
+ .cx8,
+ .fast_scalar_shift_masks,
+ .fxsr,
+ .nopl,
+ .slow_shld,
+ .slow_unaligned_mem_16,
+ .sse2,
+ .x87,
+ }),
+ };
+ pub const athlon_mp = Cpu{
+ .name = "athlon_mp",
+ .llvm_name = "athlon-mp",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .cmov,
+ .cx8,
+ .fxsr,
+ .nopl,
+ .slow_shld,
+ .slow_unaligned_mem_16,
+ .sse,
+ .x87,
+ }),
+ };
+ pub const athlon_tbird = Cpu{
+ .name = "athlon_tbird",
+ .llvm_name = "athlon-tbird",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .cmov,
+ .cx8,
+ .nopl,
+ .slow_shld,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const athlon_xp = Cpu{
+ .name = "athlon_xp",
+ .llvm_name = "athlon-xp",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .cmov,
+ .cx8,
+ .fxsr,
+ .nopl,
+ .slow_shld,
+ .slow_unaligned_mem_16,
+ .sse,
+ .x87,
+ }),
+ };
+ pub const athlon64 = Cpu{
+ .name = "athlon64",
+ .llvm_name = "athlon64",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .@"64bit",
+ .cmov,
+ .cx8,
+ .fast_scalar_shift_masks,
+ .fxsr,
+ .nopl,
+ .slow_shld,
+ .slow_unaligned_mem_16,
+ .sse2,
+ .x87,
+ }),
+ };
+ pub const athlon64_sse3 = Cpu{
+ .name = "athlon64_sse3",
+ .llvm_name = "athlon64-sse3",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fast_scalar_shift_masks,
+ .fxsr,
+ .nopl,
+ .slow_shld,
+ .slow_unaligned_mem_16,
+ .sse3,
+ .x87,
+ }),
+ };
+ pub const atom = Cpu{
+ .name = "atom",
+ .llvm_name = "atom",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fxsr,
+ .idivl_to_divb,
+ .idivq_to_divl,
+ .lea_sp,
+ .lea_uses_ag,
+ .mmx,
+ .movbe,
+ .nopl,
+ .pad_short_functions,
+ .sahf,
+ .slow_two_mem_ops,
+ .slow_unaligned_mem_16,
+ .ssse3,
+ .x87,
+ }),
+ };
+ pub const barcelona = Cpu{
+ .name = "barcelona",
+ .llvm_name = "barcelona",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fast_scalar_shift_masks,
+ .fxsr,
+ .lzcnt,
+ .nopl,
+ .popcnt,
+ .sahf,
+ .slow_shld,
+ .sse4a,
+ .x87,
+ }),
+ };
+ pub const bdver1 = Cpu{
+ .name = "bdver1",
+ .llvm_name = "bdver1",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .aes,
+ .branchfusion,
+ .cmov,
+ .cx16,
+ .cx8,
+ .fast_11bytenop,
+ .fast_scalar_shift_masks,
+ .fxsr,
+ .lwp,
+ .lzcnt,
+ .mmx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .sahf,
+ .slow_shld,
+ .x87,
+ .xop,
+ .xsave,
+ }),
+ };
+ pub const bdver2 = Cpu{
+ .name = "bdver2",
+ .llvm_name = "bdver2",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .aes,
+ .bmi,
+ .branchfusion,
+ .cmov,
+ .cx16,
+ .cx8,
+ .f16c,
+ .fast_11bytenop,
+ .fast_bextr,
+ .fast_scalar_shift_masks,
+ .fma,
+ .fxsr,
+ .lwp,
+ .lzcnt,
+ .mmx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .sahf,
+ .slow_shld,
+ .tbm,
+ .x87,
+ .xop,
+ .xsave,
+ }),
+ };
+ pub const bdver3 = Cpu{
+ .name = "bdver3",
+ .llvm_name = "bdver3",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .aes,
+ .bmi,
+ .branchfusion,
+ .cmov,
+ .cx16,
+ .cx8,
+ .f16c,
+ .fast_11bytenop,
+ .fast_bextr,
+ .fast_scalar_shift_masks,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .lwp,
+ .lzcnt,
+ .mmx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .sahf,
+ .slow_shld,
+ .tbm,
+ .x87,
+ .xop,
+ .xsave,
+ .xsaveopt,
+ }),
+ };
+ pub const bdver4 = Cpu{
+ .name = "bdver4",
+ .llvm_name = "bdver4",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .aes,
+ .avx2,
+ .bmi,
+ .bmi2,
+ .branchfusion,
+ .cmov,
+ .cx16,
+ .cx8,
+ .f16c,
+ .fast_11bytenop,
+ .fast_bextr,
+ .fast_scalar_shift_masks,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .lwp,
+ .lzcnt,
+ .mmx,
+ .mwaitx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .sahf,
+ .slow_shld,
+ .tbm,
+ .x87,
+ .xop,
+ .xsave,
+ .xsaveopt,
+ }),
+ };
+ pub const bonnell = Cpu{
+ .name = "bonnell",
+ .llvm_name = "bonnell",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fxsr,
+ .idivl_to_divb,
+ .idivq_to_divl,
+ .lea_sp,
+ .lea_uses_ag,
+ .mmx,
+ .movbe,
+ .nopl,
+ .pad_short_functions,
+ .sahf,
+ .slow_two_mem_ops,
+ .slow_unaligned_mem_16,
+ .ssse3,
+ .x87,
+ }),
+ };
+ pub const broadwell = Cpu{
+ .name = "broadwell",
+ .llvm_name = "broadwell",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .avx,
+ .avx2,
+ .bmi,
+ .bmi2,
+ .cmov,
+ .cx16,
+ .cx8,
+ .ermsb,
+ .f16c,
+ .false_deps_lzcnt_tzcnt,
+ .false_deps_popcnt,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fast_variable_shuffle,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .invpcid,
+ .lzcnt,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .movbe,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .slow_3ops_lea,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsaveopt,
+ }),
+ };
+ pub const btver1 = Cpu{
+ .name = "btver1",
+ .llvm_name = "btver1",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fast_15bytenop,
+ .fast_scalar_shift_masks,
+ .fast_vector_shift_masks,
+ .fxsr,
+ .lzcnt,
+ .mmx,
+ .nopl,
+ .popcnt,
+ .prfchw,
+ .sahf,
+ .slow_shld,
+ .sse4a,
+ .ssse3,
+ .x87,
+ }),
+ };
+ pub const btver2 = Cpu{
+ .name = "btver2",
+ .llvm_name = "btver2",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .aes,
+ .avx,
+ .bmi,
+ .cmov,
+ .cx16,
+ .cx8,
+ .f16c,
+ .fast_15bytenop,
+ .fast_bextr,
+ .fast_hops,
+ .fast_lzcnt,
+ .fast_partial_ymm_or_zmm_write,
+ .fast_scalar_shift_masks,
+ .fast_vector_shift_masks,
+ .fxsr,
+ .lzcnt,
+ .mmx,
+ .movbe,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .sahf,
+ .slow_shld,
+ .sse4a,
+ .ssse3,
+ .x87,
+ .xsave,
+ .xsaveopt,
+ }),
+ };
+ pub const c3 = Cpu{
+ .name = "c3",
+ .llvm_name = "c3",
+ .features = featureSet(&[_]Feature{
+ .@"3dnow",
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const c3_2 = Cpu{
+ .name = "c3_2",
+ .llvm_name = "c3-2",
+ .features = featureSet(&[_]Feature{
+ .cmov,
+ .cx8,
+ .fxsr,
+ .mmx,
+ .slow_unaligned_mem_16,
+ .sse,
+ .x87,
+ }),
+ };
+ pub const cannonlake = Cpu{
+ .name = "cannonlake",
+ .llvm_name = "cannonlake",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx,
+ .avx2,
+ .avx512bw,
+ .avx512cd,
+ .avx512dq,
+ .avx512f,
+ .avx512ifma,
+ .avx512vbmi,
+ .avx512vl,
+ .bmi,
+ .bmi2,
+ .clflushopt,
+ .cmov,
+ .cx16,
+ .cx8,
+ .ermsb,
+ .f16c,
+ .fast_gather,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fast_variable_shuffle,
+ .fast_vector_fsqrt,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .invpcid,
+ .lzcnt,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .movbe,
+ .mpx,
+ .nopl,
+ .pclmul,
+ .pku,
+ .popcnt,
+ .prfchw,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .sgx,
+ .sha,
+ .slow_3ops_lea,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+ pub const cascadelake = Cpu{
+ .name = "cascadelake",
+ .llvm_name = "cascadelake",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx,
+ .avx2,
+ .avx512bw,
+ .avx512cd,
+ .avx512dq,
+ .avx512f,
+ .avx512vl,
+ .avx512vnni,
+ .bmi,
+ .bmi2,
+ .clflushopt,
+ .clwb,
+ .cmov,
+ .cx16,
+ .cx8,
+ .ermsb,
+ .f16c,
+ .false_deps_popcnt,
+ .fast_gather,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fast_variable_shuffle,
+ .fast_vector_fsqrt,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .invpcid,
+ .lzcnt,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .movbe,
+ .mpx,
+ .nopl,
+ .pclmul,
+ .pku,
+ .popcnt,
+ .prfchw,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .slow_3ops_lea,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+ pub const cooperlake = Cpu{
+ .name = "cooperlake",
+ .llvm_name = "cooperlake",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx,
+ .avx2,
+ .avx512bf16,
+ .avx512bw,
+ .avx512cd,
+ .avx512dq,
+ .avx512f,
+ .avx512vl,
+ .avx512vnni,
+ .bmi,
+ .bmi2,
+ .clflushopt,
+ .clwb,
+ .cmov,
+ .cx16,
+ .cx8,
+ .ermsb,
+ .f16c,
+ .false_deps_popcnt,
+ .fast_gather,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fast_variable_shuffle,
+ .fast_vector_fsqrt,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .invpcid,
+ .lzcnt,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .movbe,
+ .mpx,
+ .nopl,
+ .pclmul,
+ .pku,
+ .popcnt,
+ .prfchw,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .slow_3ops_lea,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+ pub const core_avx_i = Cpu{
+ .name = "core_avx_i",
+ .llvm_name = "core-avx-i",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .avx,
+ .cmov,
+ .cx16,
+ .cx8,
+ .f16c,
+ .false_deps_popcnt,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .rdrnd,
+ .sahf,
+ .slow_3ops_lea,
+ .slow_unaligned_mem_32,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsaveopt,
+ }),
+ };
+ pub const core_avx2 = Cpu{
+ .name = "core_avx2",
+ .llvm_name = "core-avx2",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .avx,
+ .avx2,
+ .bmi,
+ .bmi2,
+ .cmov,
+ .cx16,
+ .cx8,
+ .ermsb,
+ .f16c,
+ .false_deps_lzcnt_tzcnt,
+ .false_deps_popcnt,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fast_variable_shuffle,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .invpcid,
+ .lzcnt,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .movbe,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .rdrnd,
+ .sahf,
+ .slow_3ops_lea,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsaveopt,
+ }),
+ };
+ pub const core2 = Cpu{
+ .name = "core2",
+ .llvm_name = "core2",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fxsr,
+ .macrofusion,
+ .mmx,
+ .nopl,
+ .sahf,
+ .slow_unaligned_mem_16,
+ .ssse3,
+ .x87,
+ }),
+ };
+ pub const corei7 = Cpu{
+ .name = "corei7",
+ .llvm_name = "corei7",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fxsr,
+ .macrofusion,
+ .mmx,
+ .nopl,
+ .popcnt,
+ .sahf,
+ .sse4_2,
+ .x87,
+ }),
+ };
+ pub const corei7_avx = Cpu{
+ .name = "corei7_avx",
+ .llvm_name = "corei7-avx",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .avx,
+ .cmov,
+ .cx16,
+ .cx8,
+ .false_deps_popcnt,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fxsr,
+ .idivq_to_divl,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .sahf,
+ .slow_3ops_lea,
+ .slow_unaligned_mem_32,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsaveopt,
+ }),
+ };
+ pub const generic = Cpu{
+ .name = "generic",
+ .llvm_name = "generic",
+ .features = featureSet(&[_]Feature{
+ .cx8,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const geode = Cpu{
+ .name = "geode",
+ .llvm_name = "geode",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .cx8,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const goldmont = Cpu{
+ .name = "goldmont",
+ .llvm_name = "goldmont",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .aes,
+ .clflushopt,
+ .cmov,
+ .cx16,
+ .cx8,
+ .false_deps_popcnt,
+ .fsgsbase,
+ .fxsr,
+ .mmx,
+ .movbe,
+ .mpx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .sha,
+ .slow_incdec,
+ .slow_lea,
+ .slow_two_mem_ops,
+ .sse4_2,
+ .ssse3,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+ pub const goldmont_plus = Cpu{
+ .name = "goldmont_plus",
+ .llvm_name = "goldmont-plus",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .aes,
+ .clflushopt,
+ .cmov,
+ .cx16,
+ .cx8,
+ .fsgsbase,
+ .fxsr,
+ .mmx,
+ .movbe,
+ .mpx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .ptwrite,
+ .rdpid,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .sgx,
+ .sha,
+ .slow_incdec,
+ .slow_lea,
+ .slow_two_mem_ops,
+ .sse4_2,
+ .ssse3,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+ pub const haswell = Cpu{
+ .name = "haswell",
+ .llvm_name = "haswell",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .avx,
+ .avx2,
+ .bmi,
+ .bmi2,
+ .cmov,
+ .cx16,
+ .cx8,
+ .ermsb,
+ .f16c,
+ .false_deps_lzcnt_tzcnt,
+ .false_deps_popcnt,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fast_variable_shuffle,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .invpcid,
+ .lzcnt,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .movbe,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .rdrnd,
+ .sahf,
+ .slow_3ops_lea,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsaveopt,
+ }),
+ };
+ pub const _i386 = Cpu{
+ .name = "_i386",
+ .llvm_name = "i386",
+ .features = featureSet(&[_]Feature{
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const _i486 = Cpu{
+ .name = "_i486",
+ .llvm_name = "i486",
+ .features = featureSet(&[_]Feature{
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const _i586 = Cpu{
+ .name = "_i586",
+ .llvm_name = "i586",
+ .features = featureSet(&[_]Feature{
+ .cx8,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const _i686 = Cpu{
+ .name = "_i686",
+ .llvm_name = "i686",
+ .features = featureSet(&[_]Feature{
+ .cmov,
+ .cx8,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const icelake_client = Cpu{
+ .name = "icelake_client",
+ .llvm_name = "icelake-client",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx,
+ .avx2,
+ .avx512bitalg,
+ .avx512bw,
+ .avx512cd,
+ .avx512dq,
+ .avx512f,
+ .avx512ifma,
+ .avx512vbmi,
+ .avx512vbmi2,
+ .avx512vl,
+ .avx512vnni,
+ .avx512vpopcntdq,
+ .bmi,
+ .bmi2,
+ .clflushopt,
+ .clwb,
+ .cmov,
+ .cx16,
+ .cx8,
+ .ermsb,
+ .f16c,
+ .fast_gather,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fast_variable_shuffle,
+ .fast_vector_fsqrt,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .gfni,
+ .idivq_to_divl,
+ .invpcid,
+ .lzcnt,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .movbe,
+ .mpx,
+ .nopl,
+ .pclmul,
+ .pku,
+ .popcnt,
+ .prfchw,
+ .rdpid,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .sgx,
+ .sha,
+ .slow_3ops_lea,
+ .sse4_2,
+ .vaes,
+ .vpclmulqdq,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+ pub const icelake_server = Cpu{
+ .name = "icelake_server",
+ .llvm_name = "icelake-server",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx,
+ .avx2,
+ .avx512bitalg,
+ .avx512bw,
+ .avx512cd,
+ .avx512dq,
+ .avx512f,
+ .avx512ifma,
+ .avx512vbmi,
+ .avx512vbmi2,
+ .avx512vl,
+ .avx512vnni,
+ .avx512vpopcntdq,
+ .bmi,
+ .bmi2,
+ .clflushopt,
+ .clwb,
+ .cmov,
+ .cx16,
+ .cx8,
+ .ermsb,
+ .f16c,
+ .fast_gather,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fast_variable_shuffle,
+ .fast_vector_fsqrt,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .gfni,
+ .idivq_to_divl,
+ .invpcid,
+ .lzcnt,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .movbe,
+ .mpx,
+ .nopl,
+ .pclmul,
+ .pconfig,
+ .pku,
+ .popcnt,
+ .prfchw,
+ .rdpid,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .sgx,
+ .sha,
+ .slow_3ops_lea,
+ .sse4_2,
+ .vaes,
+ .vpclmulqdq,
+ .wbnoinvd,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+ pub const ivybridge = Cpu{
+ .name = "ivybridge",
+ .llvm_name = "ivybridge",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .avx,
+ .cmov,
+ .cx16,
+ .cx8,
+ .f16c,
+ .false_deps_popcnt,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .rdrnd,
+ .sahf,
+ .slow_3ops_lea,
+ .slow_unaligned_mem_32,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsaveopt,
+ }),
+ };
+ pub const k6 = Cpu{
+ .name = "k6",
+ .llvm_name = "k6",
+ .features = featureSet(&[_]Feature{
+ .cx8,
+ .mmx,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const k6_2 = Cpu{
+ .name = "k6_2",
+ .llvm_name = "k6-2",
+ .features = featureSet(&[_]Feature{
+ .@"3dnow",
+ .cx8,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const k6_3 = Cpu{
+ .name = "k6_3",
+ .llvm_name = "k6-3",
+ .features = featureSet(&[_]Feature{
+ .@"3dnow",
+ .cx8,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const k8 = Cpu{
+ .name = "k8",
+ .llvm_name = "k8",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .@"64bit",
+ .cmov,
+ .cx8,
+ .fast_scalar_shift_masks,
+ .fxsr,
+ .nopl,
+ .slow_shld,
+ .slow_unaligned_mem_16,
+ .sse2,
+ .x87,
+ }),
+ };
+ pub const k8_sse3 = Cpu{
+ .name = "k8_sse3",
+ .llvm_name = "k8-sse3",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fast_scalar_shift_masks,
+ .fxsr,
+ .nopl,
+ .slow_shld,
+ .slow_unaligned_mem_16,
+ .sse3,
+ .x87,
+ }),
+ };
+ pub const knl = Cpu{
+ .name = "knl",
+ .llvm_name = "knl",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx512cd,
+ .avx512er,
+ .avx512f,
+ .avx512pf,
+ .bmi,
+ .bmi2,
+ .cmov,
+ .cx16,
+ .cx8,
+ .f16c,
+ .fast_gather,
+ .fast_partial_ymm_or_zmm_write,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .lzcnt,
+ .mmx,
+ .movbe,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prefetchwt1,
+ .prfchw,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .slow_3ops_lea,
+ .slow_incdec,
+ .slow_pmaddwd,
+ .slow_two_mem_ops,
+ .x87,
+ .xsave,
+ .xsaveopt,
+ }),
+ };
+ pub const knm = Cpu{
+ .name = "knm",
+ .llvm_name = "knm",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx512cd,
+ .avx512er,
+ .avx512f,
+ .avx512pf,
+ .avx512vpopcntdq,
+ .bmi,
+ .bmi2,
+ .cmov,
+ .cx16,
+ .cx8,
+ .f16c,
+ .fast_gather,
+ .fast_partial_ymm_or_zmm_write,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .lzcnt,
+ .mmx,
+ .movbe,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prefetchwt1,
+ .prfchw,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .slow_3ops_lea,
+ .slow_incdec,
+ .slow_pmaddwd,
+ .slow_two_mem_ops,
+ .x87,
+ .xsave,
+ .xsaveopt,
+ }),
+ };
+ pub const lakemont = Cpu{
+ .name = "lakemont",
+ .llvm_name = "lakemont",
+ .features = featureSet(&[_]Feature{}),
+ };
+ pub const nehalem = Cpu{
+ .name = "nehalem",
+ .llvm_name = "nehalem",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fxsr,
+ .macrofusion,
+ .mmx,
+ .nopl,
+ .popcnt,
+ .sahf,
+ .sse4_2,
+ .x87,
+ }),
+ };
+ pub const nocona = Cpu{
+ .name = "nocona",
+ .llvm_name = "nocona",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fxsr,
+ .mmx,
+ .nopl,
+ .slow_unaligned_mem_16,
+ .sse3,
+ .x87,
+ }),
+ };
+ pub const opteron = Cpu{
+ .name = "opteron",
+ .llvm_name = "opteron",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .@"64bit",
+ .cmov,
+ .cx8,
+ .fast_scalar_shift_masks,
+ .fxsr,
+ .nopl,
+ .slow_shld,
+ .slow_unaligned_mem_16,
+ .sse2,
+ .x87,
+ }),
+ };
+ pub const opteron_sse3 = Cpu{
+ .name = "opteron_sse3",
+ .llvm_name = "opteron-sse3",
+ .features = featureSet(&[_]Feature{
+ .@"3dnowa",
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fast_scalar_shift_masks,
+ .fxsr,
+ .nopl,
+ .slow_shld,
+ .slow_unaligned_mem_16,
+ .sse3,
+ .x87,
+ }),
+ };
+ pub const penryn = Cpu{
+ .name = "penryn",
+ .llvm_name = "penryn",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fxsr,
+ .macrofusion,
+ .mmx,
+ .nopl,
+ .sahf,
+ .slow_unaligned_mem_16,
+ .sse4_1,
+ .x87,
+ }),
+ };
+ pub const pentium = Cpu{
+ .name = "pentium",
+ .llvm_name = "pentium",
+ .features = featureSet(&[_]Feature{
+ .cx8,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const pentium_m = Cpu{
+ .name = "pentium_m",
+ .llvm_name = "pentium-m",
+ .features = featureSet(&[_]Feature{
+ .cmov,
+ .cx8,
+ .fxsr,
+ .mmx,
+ .nopl,
+ .slow_unaligned_mem_16,
+ .sse2,
+ .x87,
+ }),
+ };
+ pub const pentium_mmx = Cpu{
+ .name = "pentium_mmx",
+ .llvm_name = "pentium-mmx",
+ .features = featureSet(&[_]Feature{
+ .cx8,
+ .mmx,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const pentium2 = Cpu{
+ .name = "pentium2",
+ .llvm_name = "pentium2",
+ .features = featureSet(&[_]Feature{
+ .cmov,
+ .cx8,
+ .fxsr,
+ .mmx,
+ .nopl,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const pentium3 = Cpu{
+ .name = "pentium3",
+ .llvm_name = "pentium3",
+ .features = featureSet(&[_]Feature{
+ .cmov,
+ .cx8,
+ .fxsr,
+ .mmx,
+ .nopl,
+ .slow_unaligned_mem_16,
+ .sse,
+ .x87,
+ }),
+ };
+ pub const pentium3m = Cpu{
+ .name = "pentium3m",
+ .llvm_name = "pentium3m",
+ .features = featureSet(&[_]Feature{
+ .cmov,
+ .cx8,
+ .fxsr,
+ .mmx,
+ .nopl,
+ .slow_unaligned_mem_16,
+ .sse,
+ .x87,
+ }),
+ };
+ pub const pentium4 = Cpu{
+ .name = "pentium4",
+ .llvm_name = "pentium4",
+ .features = featureSet(&[_]Feature{
+ .cmov,
+ .cx8,
+ .fxsr,
+ .mmx,
+ .nopl,
+ .slow_unaligned_mem_16,
+ .sse2,
+ .x87,
+ }),
+ };
+ pub const pentium4m = Cpu{
+ .name = "pentium4m",
+ .llvm_name = "pentium4m",
+ .features = featureSet(&[_]Feature{
+ .cmov,
+ .cx8,
+ .fxsr,
+ .mmx,
+ .nopl,
+ .slow_unaligned_mem_16,
+ .sse2,
+ .x87,
+ }),
+ };
+ pub const pentiumpro = Cpu{
+ .name = "pentiumpro",
+ .llvm_name = "pentiumpro",
+ .features = featureSet(&[_]Feature{
+ .cmov,
+ .cx8,
+ .nopl,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const prescott = Cpu{
+ .name = "prescott",
+ .llvm_name = "prescott",
+ .features = featureSet(&[_]Feature{
+ .cmov,
+ .cx8,
+ .fxsr,
+ .mmx,
+ .nopl,
+ .slow_unaligned_mem_16,
+ .sse3,
+ .x87,
+ }),
+ };
+ pub const sandybridge = Cpu{
+ .name = "sandybridge",
+ .llvm_name = "sandybridge",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .avx,
+ .cmov,
+ .cx16,
+ .cx8,
+ .false_deps_popcnt,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fxsr,
+ .idivq_to_divl,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .sahf,
+ .slow_3ops_lea,
+ .slow_unaligned_mem_32,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsaveopt,
+ }),
+ };
+ pub const silvermont = Cpu{
+ .name = "silvermont",
+ .llvm_name = "silvermont",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .false_deps_popcnt,
+ .fxsr,
+ .idivq_to_divl,
+ .mmx,
+ .movbe,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .rdrnd,
+ .sahf,
+ .slow_incdec,
+ .slow_lea,
+ .slow_pmulld,
+ .slow_two_mem_ops,
+ .sse4_2,
+ .ssse3,
+ .x87,
+ }),
+ };
+ pub const skx = Cpu{
+ .name = "skx",
+ .llvm_name = "skx",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx,
+ .avx2,
+ .avx512bw,
+ .avx512cd,
+ .avx512dq,
+ .avx512f,
+ .avx512vl,
+ .bmi,
+ .bmi2,
+ .clflushopt,
+ .clwb,
+ .cmov,
+ .cx16,
+ .cx8,
+ .ermsb,
+ .f16c,
+ .false_deps_popcnt,
+ .fast_gather,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fast_variable_shuffle,
+ .fast_vector_fsqrt,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .invpcid,
+ .lzcnt,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .movbe,
+ .mpx,
+ .nopl,
+ .pclmul,
+ .pku,
+ .popcnt,
+ .prfchw,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .slow_3ops_lea,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+ pub const skylake = Cpu{
+ .name = "skylake",
+ .llvm_name = "skylake",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx,
+ .avx2,
+ .bmi,
+ .bmi2,
+ .clflushopt,
+ .cmov,
+ .cx16,
+ .cx8,
+ .ermsb,
+ .f16c,
+ .false_deps_popcnt,
+ .fast_gather,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fast_variable_shuffle,
+ .fast_vector_fsqrt,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .invpcid,
+ .lzcnt,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .movbe,
+ .mpx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .sgx,
+ .slow_3ops_lea,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+ pub const skylake_avx512 = Cpu{
+ .name = "skylake_avx512",
+ .llvm_name = "skylake-avx512",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx,
+ .avx2,
+ .avx512bw,
+ .avx512cd,
+ .avx512dq,
+ .avx512f,
+ .avx512vl,
+ .bmi,
+ .bmi2,
+ .clflushopt,
+ .clwb,
+ .cmov,
+ .cx16,
+ .cx8,
+ .ermsb,
+ .f16c,
+ .false_deps_popcnt,
+ .fast_gather,
+ .fast_scalar_fsqrt,
+ .fast_shld_rotate,
+ .fast_variable_shuffle,
+ .fast_vector_fsqrt,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .idivq_to_divl,
+ .invpcid,
+ .lzcnt,
+ .macrofusion,
+ .merge_to_threeway_branch,
+ .mmx,
+ .movbe,
+ .mpx,
+ .nopl,
+ .pclmul,
+ .pku,
+ .popcnt,
+ .prfchw,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .slow_3ops_lea,
+ .sse4_2,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+ pub const slm = Cpu{
+ .name = "slm",
+ .llvm_name = "slm",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .false_deps_popcnt,
+ .fxsr,
+ .idivq_to_divl,
+ .mmx,
+ .movbe,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .rdrnd,
+ .sahf,
+ .slow_incdec,
+ .slow_lea,
+ .slow_pmulld,
+ .slow_two_mem_ops,
+ .sse4_2,
+ .ssse3,
+ .x87,
+ }),
+ };
+ pub const tremont = Cpu{
+ .name = "tremont",
+ .llvm_name = "tremont",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .aes,
+ .cldemote,
+ .clflushopt,
+ .cmov,
+ .cx16,
+ .cx8,
+ .fsgsbase,
+ .fxsr,
+ .gfni,
+ .mmx,
+ .movbe,
+ .movdir64b,
+ .movdiri,
+ .mpx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .ptwrite,
+ .rdpid,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .sgx,
+ .sha,
+ .slow_incdec,
+ .slow_lea,
+ .slow_two_mem_ops,
+ .sse4_2,
+ .ssse3,
+ .waitpkg,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+ pub const westmere = Cpu{
+ .name = "westmere",
+ .llvm_name = "westmere",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .cmov,
+ .cx16,
+ .cx8,
+ .fxsr,
+ .macrofusion,
+ .mmx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .sahf,
+ .sse4_2,
+ .x87,
+ }),
+ };
+ pub const winchip_c6 = Cpu{
+ .name = "winchip_c6",
+ .llvm_name = "winchip-c6",
+ .features = featureSet(&[_]Feature{
+ .mmx,
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const winchip2 = Cpu{
+ .name = "winchip2",
+ .llvm_name = "winchip2",
+ .features = featureSet(&[_]Feature{
+ .@"3dnow",
+ .slow_unaligned_mem_16,
+ .x87,
+ }),
+ };
+ pub const x86_64 = Cpu{
+ .name = "x86_64",
+ .llvm_name = "x86-64",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .cmov,
+ .cx8,
+ .fxsr,
+ .macrofusion,
+ .mmx,
+ .nopl,
+ .slow_3ops_lea,
+ .slow_incdec,
+ .sse2,
+ .x87,
+ }),
+ };
+ pub const yonah = Cpu{
+ .name = "yonah",
+ .llvm_name = "yonah",
+ .features = featureSet(&[_]Feature{
+ .cmov,
+ .cx8,
+ .fxsr,
+ .mmx,
+ .nopl,
+ .slow_unaligned_mem_16,
+ .sse3,
+ .x87,
+ }),
+ };
+ pub const znver1 = Cpu{
+ .name = "znver1",
+ .llvm_name = "znver1",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx2,
+ .bmi,
+ .bmi2,
+ .branchfusion,
+ .clflushopt,
+ .clzero,
+ .cmov,
+ .cx16,
+ .f16c,
+ .fast_15bytenop,
+ .fast_bextr,
+ .fast_lzcnt,
+ .fast_scalar_shift_masks,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .lzcnt,
+ .mmx,
+ .movbe,
+ .mwaitx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .sha,
+ .slow_shld,
+ .sse4a,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+ pub const znver2 = Cpu{
+ .name = "znver2",
+ .llvm_name = "znver2",
+ .features = featureSet(&[_]Feature{
+ .@"64bit",
+ .adx,
+ .aes,
+ .avx2,
+ .bmi,
+ .bmi2,
+ .branchfusion,
+ .clflushopt,
+ .clwb,
+ .clzero,
+ .cmov,
+ .cx16,
+ .f16c,
+ .fast_15bytenop,
+ .fast_bextr,
+ .fast_lzcnt,
+ .fast_scalar_shift_masks,
+ .fma,
+ .fsgsbase,
+ .fxsr,
+ .lzcnt,
+ .mmx,
+ .movbe,
+ .mwaitx,
+ .nopl,
+ .pclmul,
+ .popcnt,
+ .prfchw,
+ .rdpid,
+ .rdrnd,
+ .rdseed,
+ .sahf,
+ .sha,
+ .slow_shld,
+ .sse4a,
+ .wbnoinvd,
+ .x87,
+ .xsave,
+ .xsavec,
+ .xsaveopt,
+ .xsaves,
+ }),
+ };
+};
+
+/// All x86 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.amdfam10,
+ &cpu.athlon,
+ &cpu.athlon_4,
+ &cpu.athlon_fx,
+ &cpu.athlon_mp,
+ &cpu.athlon_tbird,
+ &cpu.athlon_xp,
+ &cpu.athlon64,
+ &cpu.athlon64_sse3,
+ &cpu.atom,
+ &cpu.barcelona,
+ &cpu.bdver1,
+ &cpu.bdver2,
+ &cpu.bdver3,
+ &cpu.bdver4,
+ &cpu.bonnell,
+ &cpu.broadwell,
+ &cpu.btver1,
+ &cpu.btver2,
+ &cpu.c3,
+ &cpu.c3_2,
+ &cpu.cannonlake,
+ &cpu.cascadelake,
+ &cpu.cooperlake,
+ &cpu.core_avx_i,
+ &cpu.core_avx2,
+ &cpu.core2,
+ &cpu.corei7,
+ &cpu.corei7_avx,
+ &cpu.generic,
+ &cpu.geode,
+ &cpu.goldmont,
+ &cpu.goldmont_plus,
+ &cpu.haswell,
+ &cpu._i386,
+ &cpu._i486,
+ &cpu._i586,
+ &cpu._i686,
+ &cpu.icelake_client,
+ &cpu.icelake_server,
+ &cpu.ivybridge,
+ &cpu.k6,
+ &cpu.k6_2,
+ &cpu.k6_3,
+ &cpu.k8,
+ &cpu.k8_sse3,
+ &cpu.knl,
+ &cpu.knm,
+ &cpu.lakemont,
+ &cpu.nehalem,
+ &cpu.nocona,
+ &cpu.opteron,
+ &cpu.opteron_sse3,
+ &cpu.penryn,
+ &cpu.pentium,
+ &cpu.pentium_m,
+ &cpu.pentium_mmx,
+ &cpu.pentium2,
+ &cpu.pentium3,
+ &cpu.pentium3m,
+ &cpu.pentium4,
+ &cpu.pentium4m,
+ &cpu.pentiumpro,
+ &cpu.prescott,
+ &cpu.sandybridge,
+ &cpu.silvermont,
+ &cpu.skx,
+ &cpu.skylake,
+ &cpu.skylake_avx512,
+ &cpu.slm,
+ &cpu.tremont,
+ &cpu.westmere,
+ &cpu.winchip_c6,
+ &cpu.winchip2,
+ &cpu.x86_64,
+ &cpu.yonah,
+ &cpu.znver1,
+ &cpu.znver2,
+};