structstd.Target.Cpu.Feature[src]

Types

Type FunctionFeatureSetFns[src]

Parameters

F: type

Functions

FunctionfeatureSet[src]

pub fn featureSet(features: []const F) Set

Populates only the feature bits specified.

Parameters

features: []const F

Source Code

Source code
pub fn featureSet(features: []const F) Set {
    var x = Set.empty;
    for (features) |feature| {
        x.addFeature(@intFromEnum(feature));
    }
    return x;
}

FunctionfeatureSetHas[src]

pub fn featureSetHas(set: Set, feature: F) bool

Returns true if the specified feature is enabled.

Parameters

set: Set
feature: F

Source Code

Source code
pub fn featureSetHas(set: Set, feature: F) bool {
    return set.isEnabled(@intFromEnum(feature));
}

FunctionfeatureSetHasAny[src]

pub fn featureSetHasAny(set: Set, features: anytype) bool

Returns true if any specified feature is enabled.

Parameters

set: Set

Source Code

Source code
pub fn featureSetHasAny(set: Set, features: anytype) bool {
    inline for (features) |feature| {
        if (set.isEnabled(@intFromEnum(@as(F, feature)))) return true;
    }
    return false;
}

FunctionfeatureSetHasAll[src]

pub fn featureSetHasAll(set: Set, features: anytype) bool

Returns true if every specified feature is enabled.

Parameters

set: Set

Source Code

Source code
pub fn featureSetHasAll(set: Set, features: anytype) bool {
    inline for (features) |feature| {
        if (!set.isEnabled(@intFromEnum(@as(F, feature)))) return false;
    }
    return true;
}

Source Code

Source code
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;
        }
    };
}

Fields

index: Set.Index = undefined

The bit index into Set. Has a default value of undefined because the canonical structures are populated via comptime logic.

name: []const u8 = undefined

Has a default value of undefined because the canonical structures are populated via comptime logic.

llvm_name: ?[:0]const u8

If this corresponds to an LLVM-recognized feature, this will be populated; otherwise null.

description: []const u8

Human-friendly UTF-8 text.

dependencies: Set

Sparse Set of features this depends on.

Source Code

Source code
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;
            }
        };
    }
}