Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

Attribute

Builder.Attribute
pub const Attribute = union(Kind)

File

lib/std/zig/llvm/Builder.zig:936

Code

pub const Attribute = union(Kind) {
    // Parameter Attributes
    zeroext,
    signext,
    inreg,
    byval: Type,
    byref: Type,
    preallocated: Type,
    inalloca: Type,
    sret: Type,
    elementtype: Type,
    @"align": Alignment.Lazy,
    @"noalias",
    nocapture,
    nofree,
    nest,
    returned,
    nonnull,
    dereferenceable: u32,
    dereferenceable_or_null: u32,
    swiftself,
    swiftasync,
    swifterror,
    immarg,
    noundef,
    nofpclass: FpClass,
    alignstack: Alignment.Lazy,
    allocalign,
    allocptr,
    readnone,
    readonly,
    writeonly,

    // Function Attributes
    //alignstack: Alignment.Lazy,
    allockind: AllocKind,
    allocsize: AllocSize,
    alwaysinline,
    builtin,
    cold,
    convergent,
    disable_sanitizer_information,
    fn_ret_thunk_extern,
    hot,
    inlinehint,
    jumptable,
    memory: Memory,
    minsize,
    naked,
    nobuiltin,
    nocallback,
    noduplicate,
    //nofree,
    noimplicitfloat,
    @"noinline",
    nomerge,
    nonlazybind,
    noprofile,
    skipprofile,
    noredzone,
    noreturn,
    norecurse,
    willreturn,
    nosync,
    nounwind,
    nosanitize_bounds,
    nosanitize_coverage,
    null_pointer_is_valid,
    optforfuzzing,
    optnone,
    optsize,
    //preallocated: Type,
    returns_twice,
    safestack,
    sanitize_address,
    sanitize_memory,
    sanitize_thread,
    sanitize_hwaddress,
    sanitize_memtag,
    speculative_load_hardening,
    speculatable,
    ssp,
    sspstrong,
    sspreq,
    strictfp,
    uwtable: UwTable,
    nocf_check,
    shadowcallstack,
    mustprogress,
    vscale_range: VScaleRange,

    // Global Attributes
    no_sanitize_address,
    no_sanitize_hwaddress,
    //sanitize_memtag,
    sanitize_address_dyninit,

    string: struct { kind: String, value: String },
    none: noreturn,

    pub const Index = enum(u32) {
        _,

        pub fn getKind(self: Index, builder: *const Builder) Kind {
            return self.toStorage(builder).kind;
        }

        pub fn toAttribute(self: Index, builder: *const Builder) Attribute {
            @setEvalBranchQuota(2_000);
            const storage = self.toStorage(builder);
            if (storage.kind.toString()) |kind| return .{ .string = .{
                .kind = kind,
                .value = @fromBackingInt(@intCast(storage.value)),
            } } else return switch (storage.kind) {
                inline .zeroext,
                .signext,
                .inreg,
                .byval,
                .byref,
                .preallocated,
                .inalloca,
                .sret,
                .elementtype,
                .@"align",
                .@"noalias",
                .nocapture,
                .nofree,
                .nest,
                .returned,
                .nonnull,
                .dereferenceable,
                .dereferenceable_or_null,
                .swiftself,
                .swiftasync,
                .swifterror,
                .immarg,
                .noundef,
                .nofpclass,
                .alignstack,
                .allocalign,
                .allocptr,
                .readnone,
                .readonly,
                .writeonly,
                //.alignstack,
                .allockind,
                .allocsize,
                .alwaysinline,
                .builtin,
                .cold,
                .convergent,
                .disable_sanitizer_information,
                .fn_ret_thunk_extern,
                .hot,
                .inlinehint,
                .jumptable,
                .memory,
                .minsize,
                .naked,
                .nobuiltin,
                .nocallback,
                .noduplicate,
                //.nofree,
                .noimplicitfloat,
                .@"noinline",
                .nomerge,
                .nonlazybind,
                .noprofile,
                .skipprofile,
                .noredzone,
                .noreturn,
                .norecurse,
                .willreturn,
                .nosync,
                .nounwind,
                .nosanitize_bounds,
                .nosanitize_coverage,
                .null_pointer_is_valid,
                .optforfuzzing,
                .optnone,
                .optsize,
                //.preallocated,
                .returns_twice,
                .safestack,
                .sanitize_address,
                .sanitize_memory,
                .sanitize_thread,
                .sanitize_hwaddress,
                .sanitize_memtag,
                .speculative_load_hardening,
                .speculatable,
                .ssp,
                .sspstrong,
                .sspreq,
                .strictfp,
                .uwtable,
                .nocf_check,
                .shadowcallstack,
                .mustprogress,
                .vscale_range,
                .no_sanitize_address,
                .no_sanitize_hwaddress,
                .sanitize_address_dyninit,
                => |kind| {
                    const field_name, const field_type = comptime blk: {
                        @setEvalBranchQuota(10_000);
                        const info = @typeInfo(Attribute).@"union";
                        for (info.field_names, info.field_types) |field_name, field_type| {
                            if (std.mem.eql(u8, field_name, @tagName(kind))) break :blk .{ field_name, field_type };
                        }
                        unreachable;
                    };
                    comptime assert(std.mem.eql(u8, @tagName(kind), field_name));
                    return @unionInit(Attribute, field_name, switch (field_type) {
                        void => {},
                        u32 => storage.value,
                        Alignment.Lazy, String, Type, UwTable => @fromBackingInt(@intCast(storage.value)),
                        AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value),
                        else => @compileError("bad payload type: " ++ field_name ++ ": " ++
                            @typeName(field_type)),
                    });
                },
                .string, .none => unreachable,
                _ => unreachable,
            };
        }

        const FormatData = struct {
            attribute_index: Index,
            builder: *const Builder,
            flags: Flags = .{},
            const Flags = struct {
                pound: bool = false,
                quote: bool = false,
            };
        };
        fn format(data: FormatData, w: *Writer) Writer.Error!void {
            const attribute = data.attribute_index.toAttribute(data.builder);
            switch (attribute) {
                .zeroext,
                .signext,
                .inreg,
                .@"noalias",
                .nocapture,
                .nofree,
                .nest,
                .returned,
                .nonnull,
                .swiftself,
                .swiftasync,
                .swifterror,
                .immarg,
                .noundef,
                .allocalign,
                .allocptr,
                .readnone,
                .readonly,
                .writeonly,
                .alwaysinline,
                .builtin,
                .cold,
                .convergent,
                .disable_sanitizer_information,
                .fn_ret_thunk_extern,
                .hot,
                .inlinehint,
                .jumptable,
                .minsize,
                .naked,
                .nobuiltin,
                .nocallback,
                .noduplicate,
                .noimplicitfloat,
                .@"noinline",
                .nomerge,
                .nonlazybind,
                .noprofile,
                .skipprofile,
                .noredzone,
                .noreturn,
                .norecurse,
                .willreturn,
                .nosync,
                .nounwind,
                .nosanitize_bounds,
                .nosanitize_coverage,
                .null_pointer_is_valid,
                .optforfuzzing,
                .optnone,
                .optsize,
                .returns_twice,
                .safestack,
                .sanitize_address,
                .sanitize_memory,
                .sanitize_thread,
                .sanitize_hwaddress,
                .sanitize_memtag,
                .speculative_load_hardening,
                .speculatable,
                .ssp,
                .sspstrong,
                .sspreq,
                .strictfp,
                .nocf_check,
                .shadowcallstack,
                .mustprogress,
                .no_sanitize_address,
                .no_sanitize_hwaddress,
                .sanitize_address_dyninit,
                => try w.print(" {s}", .{@tagName(attribute)}),
                .byval,
                .byref,
                .preallocated,
                .inalloca,
                .sret,
                .elementtype,
                => |ty| try w.print(" {s}({f})", .{ @tagName(attribute), ty.fmt(data.builder, .percent) }),
                .@"align" => |alignment| try w.print("{f}", .{alignment.resolve(data.builder).fmt(" ")}),
                .dereferenceable,
                .dereferenceable_or_null,
                => |size| try w.print(" {s}({d})", .{ @tagName(attribute), size }),
                .nofpclass => |fpclass| {
                    const Int = @typeInfo(FpClass).@"struct".backing_integer.?;
                    try w.print(" {s}(", .{@tagName(attribute)});
                    var any = false;
                    var remaining: Int = @bitCast(fpclass);
                    inline for (@typeInfo(FpClass).@"struct".decl_names) |decl_name| {
                        const pattern: Int = @bitCast(@field(FpClass, decl_name));
                        if (remaining & pattern == pattern) {
                            if (!any) {
                                try w.writeByte(' ');
                                any = true;
                            }
                            try w.writeAll(decl_name);
                            remaining &= ~pattern;
                        }
                    }
                    try w.writeByte(')');
                },
                .alignstack => |alignment| {
                    try w.print(" {t}", .{attribute});
                    const alignment_bytes = alignment.resolve(data.builder).toByteUnits() orelse return;
                    if (data.flags.pound) {
                        try w.print("={d}", .{alignment_bytes});
                    } else {
                        try w.print("({d})", .{alignment_bytes});
                    }
                },
                .allockind => |allockind| {
                    try w.print(" {t}(\"", .{attribute});
                    var any = false;
                    inline for (@typeInfo(AllocKind).@"struct".field_names) |field_name| {
                        if (comptime std.mem.eql(u8, field_name, "_")) continue;
                        if (@field(allockind, field_name)) {
                            if (!any) {
                                try w.writeByte(',');
                                any = true;
                            }
                            try w.writeAll(field_name);
                        }
                    }
                    try w.writeAll("\")");
                },
                .allocsize => |allocsize| {
                    try w.print(" {t}({d}", .{ attribute, allocsize.elem_size });
                    if (allocsize.num_elems != AllocSize.none)
                        try w.print(",{d}", .{allocsize.num_elems});
                    try w.writeByte(')');
                },
                .memory => |memory| {
                    try w.print(" {t}(", .{attribute});
                    var any = memory.other != .none or
                        (memory.argmem == .none and memory.inaccessiblemem == .none);
                    if (any) try w.writeAll(@tagName(memory.other));
                    inline for (.{ "argmem", "inaccessiblemem" }) |kind| {
                        if (@field(memory, kind) != memory.other) {
                            if (any) try w.writeAll(", ");
                            try w.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) });
                            any = true;
                        }
                    }
                    try w.writeByte(')');
                },
                .uwtable => |uwtable| if (uwtable != .none) {
                    try w.print(" {s}", .{@tagName(attribute)});
                    if (uwtable != UwTable.default) try w.print("({s})", .{@tagName(uwtable)});
                },
                .vscale_range => |vscale_range| try w.print(" {s}({d},{d})", .{
                    @tagName(attribute),
                    vscale_range.min.toByteUnits().?,
                    vscale_range.max.toByteUnits() orelse 0,
                }),
                .string => |string_attr| if (data.flags.quote) {
                    try w.print(" {f}", .{string_attr.kind.fmtQ(data.builder)});
                    if (string_attr.value != .empty)
                        try w.print("={f}", .{string_attr.value.fmtQ(data.builder)});
                },
                .none => unreachable,
            }
        }
        pub fn fmt(self: Index, builder: *const Builder, flags: FormatData.Flags) std.fmt.Alt(FormatData, format) {
            return .{ .data = .{ .attribute_index = self, .builder = builder, .flags = flags } };
        }

        fn toStorage(self: Index, builder: *const Builder) Storage {
            return builder.attributes.keys()[@backingInt(self)];
        }
    };

    pub const Kind = enum(u32) {
        // Parameter Attributes
        zeroext = 34,
        signext = 24,
        inreg = 5,
        byval = 3,
        byref = 69,
        preallocated = 65,
        inalloca = 38,
        sret = 29, // TODO: ?
        elementtype = 77,
        @"align" = 1,
        @"noalias" = 9,
        nocapture = 11,
        nofree = 62,
        nest = 8,
        returned = 22,
        nonnull = 39,
        dereferenceable = 41,
        dereferenceable_or_null = 42,
        swiftself = 46,
        swiftasync = 75,
        swifterror = 47,
        immarg = 60,
        noundef = 68,
        nofpclass = 87,
        alignstack = 25,
        allocalign = 80,
        allocptr = 81,
        readnone = 20,
        readonly = 21,
        writeonly = 52,

        // Function Attributes
        //alignstack,
        allockind = 82,
        allocsize = 51,
        alwaysinline = 2,
        builtin = 35,
        cold = 36,
        convergent = 43,
        disable_sanitizer_information = 78,
        fn_ret_thunk_extern = 84,
        hot = 72,
        inlinehint = 4,
        jumptable = 40,
        memory = 86,
        minsize = 6,
        naked = 7,
        nobuiltin = 10,
        nocallback = 71,
        noduplicate = 12,
        //nofree,
        noimplicitfloat = 13,
        @"noinline" = 14,
        nomerge = 66,
        nonlazybind = 15,
        noprofile = 73,
        skipprofile = 85,
        noredzone = 16,
        noreturn = 17,
        norecurse = 48,
        willreturn = 61,
        nosync = 63,
        nounwind = 18,
        nosanitize_bounds = 79,
        nosanitize_coverage = 76,
        null_pointer_is_valid = 67,
        optforfuzzing = 57,
        optnone = 37,
        optsize = 19,
        //preallocated,
        returns_twice = 23,
        safestack = 44,
        sanitize_address = 30,
        sanitize_memory = 32,
        sanitize_thread = 31,
        sanitize_hwaddress = 55,
        sanitize_memtag = 64,
        speculative_load_hardening = 59,
        speculatable = 53,
        ssp = 26,
        sspstrong = 28,
        sspreq = 27,
        strictfp = 54,
        uwtable = 33,
        nocf_check = 56,
        shadowcallstack = 58,
        mustprogress = 70,
        vscale_range = 74,

        // Global Attributes
        no_sanitize_address = 100,
        no_sanitize_hwaddress = 101,
        //sanitize_memtag,
        sanitize_address_dyninit = 102,

        string = maxInt(u31),
        none = maxInt(u32),
        _,

        pub const len = @typeInfo(Kind).@"enum".field_names.len - 2;

        pub fn fromString(str: String) Kind {
            assert(!str.isAnon());
            const kind: Kind = @fromBackingInt(@intCast(@backingInt(str)));
            assert(kind != .none);
            return kind;
        }

        fn toString(self: Kind) ?String {
            assert(self != .none);
            const str: String = @fromBackingInt(@intCast(@backingInt(self)));
            return if (str.isAnon()) null else str;
        }
    };

    pub const FpClass = packed struct(u32) {
        signaling_nan: bool = false,
        quiet_nan: bool = false,
        negative_infinity: bool = false,
        negative_normal: bool = false,
        negative_subnormal: bool = false,
        negative_zero: bool = false,
        positive_zero: bool = false,
        positive_subnormal: bool = false,
        positive_normal: bool = false,
        positive_infinity: bool = false,
        _: u22 = 0,

        pub const all = FpClass{
            .signaling_nan = true,
            .quiet_nan = true,
            .negative_infinity = true,
            .negative_normal = true,
            .negative_subnormal = true,
            .negative_zero = true,
            .positive_zero = true,
            .positive_subnormal = true,
            .positive_normal = true,
            .positive_infinity = true,
        };

        pub const nan = FpClass{ .signaling_nan = true, .quiet_nan = true };
        pub const snan = FpClass{ .signaling_nan = true };
        pub const qnan = FpClass{ .quiet_nan = true };

        pub const inf = FpClass{ .negative_infinity = true, .positive_infinity = true };
        pub const ninf = FpClass{ .negative_infinity = true };
        pub const pinf = FpClass{ .positive_infinity = true };

        pub const zero = FpClass{ .positive_zero = true, .negative_zero = true };
        pub const nzero = FpClass{ .negative_zero = true };
        pub const pzero = FpClass{ .positive_zero = true };

        pub const sub = FpClass{ .positive_subnormal = true, .negative_subnormal = true };
        pub const nsub = FpClass{ .negative_subnormal = true };
        pub const psub = FpClass{ .positive_subnormal = true };

        pub const norm = FpClass{ .positive_normal = true, .negative_normal = true };
        pub const nnorm = FpClass{ .negative_normal = true };
        pub const pnorm = FpClass{ .positive_normal = true };
    };

    pub const AllocKind = packed struct(u32) {
        alloc: bool,
        realloc: bool,
        free: bool,
        uninitialized: bool,
        zeroed: bool,
        aligned: bool,
        _: u26 = 0,
    };

    pub const AllocSize = packed struct(u32) {
        elem_size: u16,
        num_elems: u16,

        pub const none = maxInt(u16);

        fn toLlvm(self: AllocSize) packed struct(u64) { num_elems: u32, elem_size: u32 } {
            return .{ .num_elems = switch (self.num_elems) {
                else => self.num_elems,
                none => maxInt(u32),
            }, .elem_size = self.elem_size };
        }
    };

    pub const Memory = packed struct(u32) {
        argmem: Effect = .none,
        inaccessiblemem: Effect = .none,
        other: Effect = .none,
        _: u26 = 0,

        pub const Effect = enum(u2) { none, read, write, readwrite };

        fn all(effect: Effect) Memory {
            return .{ .argmem = effect, .inaccessiblemem = effect, .other = effect };
        }
    };

    pub const UwTable = enum(u32) {
        none,
        sync,
        async,

        pub const default = UwTable.async;
    };

    pub const VScaleRange = packed struct(u32) {
        min: Alignment,
        max: Alignment,
        _: u20 = 0,

        fn toLlvm(self: VScaleRange) packed struct(u64) { max: u32, min: u32 } {
            return .{
                .max = @intCast(self.max.toByteUnits() orelse 0),
                .min = @intCast(self.min.toByteUnits().?),
            };
        }
    };

    pub fn getKind(self: Attribute) Kind {
        return switch (self) {
            else => self,
            .string => |string_attr| Kind.fromString(string_attr.kind),
        };
    }

    const Storage = extern struct {
        kind: Kind,
        value: u32,
    };

    fn toStorage(self: Attribute) Storage {
        return switch (self) {
            inline else => |value, tag| .{ .kind = @as(Kind, self), .value = switch (@TypeOf(value)) {
                void => 0,
                u32 => value,
                Alignment.Lazy, String, Type, UwTable => @backingInt(value),
                AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value),
                else => @compileError("bad payload type: " ++ @tagName(tag) ++ @typeName(@TypeOf(value))),
            } },
            .string => |string_attr| .{
                .kind = Kind.fromString(string_attr.kind),
                .value = @backingInt(string_attr.value),
            },
            .none => unreachable,
        };
    }
}