struct Feature [src]

Fields

index: Set.Index = undefinedThe bit index into Set. Has a default value of undefined because the canonical structures are populated via comptime logic.
name: []const u8 = undefinedHas a default value of undefined because the canonical structures are populated via comptime logic.
llvm_name: ?[:0]const u8If this corresponds to an LLVM-recognized feature, this will be populated; otherwise null.
description: []const u8Human-friendly UTF-8 text.
dependencies: SetSparse Set of features this depends on.

Members

Source

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 = 288; 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(std.meta.Int(.unsigned, usize_count * @bitSizeOf(usize))); pub const ShiftInt = std.math.Log2Int(usize); pub const empty = Set{ .ints = [1]usize{0} ** usize_count }; pub fn isEmpty(set: Set) bool { return for (set.ints) |x| { if (x != 0) break false; } else true; } pub fn count(set: Set) std.math.IntFittingRange(0, needed_bit_count) { var sum: usize = 0; for (set.ints) |x| sum += @popCount(x); return @intCast(sum); } pub fn isEnabled(set: Set, arch_feature_index: Index) bool { const usize_index = arch_feature_index / @bitSizeOf(usize); const bit_index: ShiftInt = @intCast(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: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize)); set.ints[usize_index] |= @as(usize, 1) << bit_index; } /// Adds the specified feature set but not its dependencies. pub fn addFeatureSet(set: *Set, other_set: Set) void { if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff) { for (&set.ints, other_set.ints) |*set_int, other_set_int| set_int.* |= other_set_int; } else { set.ints = @as(@Vector(usize_count, usize), set.ints) | @as(@Vector(usize_count, usize), other_set.ints); } } /// 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: ShiftInt = @intCast(arch_feature_index % @bitSizeOf(usize)); set.ints[usize_index] &= ~(@as(usize, 1) << bit_index); } /// Removes the specified feature but not its dependents. pub fn removeFeatureSet(set: *Set, other_set: Set) void { if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff) { for (&set.ints, other_set.ints) |*set_int, other_set_int| set_int.* &= ~other_set_int; } else { set.ints = @as(@Vector(usize_count, usize), set.ints) & ~@as(@Vector(usize_count, usize), other_set.ints); } } pub fn populateDependencies(set: *Set, all_features_list: []const Cpu.Feature) void { @setEvalBranchQuota(1000000); var old = set.ints; while (true) { for (all_features_list, 0..) |feature, index_usize| { const index: Index = @intCast(index_usize); if (set.isEnabled(index)) { set.addFeatureSet(feature.dependencies); } } const nothing_changed = std.mem.eql(usize, &old, &set.ints); if (nothing_changed) return; old = set.ints; } } pub fn asBytes(set: *const Set) *const [byte_count]u8 { return std.mem.sliceAsBytes(&set.ints)[0..byte_count]; } pub fn eql(set: Set, other_set: Set) bool { return std.mem.eql(usize, &set.ints, &other_set.ints); } pub fn isSuperSetOf(set: Set, other_set: Set) bool { if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff) { var result = true; for (&set.ints, other_set.ints) |*set_int, other_set_int| result = result and (set_int.* & other_set_int) == other_set_int; return result; } else { const V = @Vector(usize_count, usize); const set_v: V = set.ints; const other_v: V = other_set.ints; return @reduce(.And, (set_v & other_v) == other_v); } } }; pub fn FeatureSetFns(comptime F: type) type { return struct { /// Populates only the feature bits specified. pub fn featureSet(features: []const F) Set { var x = Set.empty; for (features) |feature| { x.addFeature(@intFromEnum(feature)); } return x; } /// Returns true if the specified feature is enabled. pub fn featureSetHas(set: Set, feature: F) bool { return set.isEnabled(@intFromEnum(feature)); } /// Returns true if any specified feature is enabled. pub fn featureSetHasAny(set: Set, features: anytype) bool { inline for (features) |feature| { if (set.isEnabled(@intFromEnum(@as(F, feature)))) return true; } return false; } /// Returns true if every specified feature is enabled. pub fn featureSetHasAll(set: Set, features: anytype) bool { inline for (features) |feature| { if (!set.isEnabled(@intFromEnum(@as(F, feature)))) return false; } return true; } }; } }