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.

Global

Builder.Global
pub const Global = struct

File

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

Code

pub const Global = struct {
    linkage: Linkage = .external,
    preemption: Preemption = .dso_preemptable,
    visibility: Visibility = .default,
    dll_storage_class: DllStorageClass = .default,
    unnamed_addr: UnnamedAddr = .default,
    addr_space: AddrSpace = .default,
    externally_initialized: ExternallyInitialized = .default,
    type: Type,
    partition: String = .none,
    dbg: Metadata.Optional = .none,
    kind: union(enum) {
        alias: Alias.Index,
        variable: Variable.Index,
        function: Function.Index,
        replaced: Global.Index,
    },

    pub const Index = enum(u32) {
        none = maxInt(u32),
        _,

        pub fn unwrap(orig_index: Index, builder: *const Builder) Index {
            var cur = orig_index;
            while (true) {
                switch (builder.globals.values()[@backingInt(cur)].kind) {
                    .replaced => |replacement| cur = replacement,
                    else => return cur,
                }
            }
        }

        pub fn eql(self: Index, other: Index, builder: *const Builder) bool {
            return self.unwrap(builder) == other.unwrap(builder);
        }

        pub fn ptr(self: Index, builder: *Builder) *Global {
            return &builder.globals.values()[@backingInt(self.unwrap(builder))];
        }

        pub fn ptrConst(self: Index, builder: *const Builder) *const Global {
            return &builder.globals.values()[@backingInt(self.unwrap(builder))];
        }

        pub fn name(self: Index, builder: *const Builder) StrtabString {
            return builder.globals.keys()[@backingInt(self.unwrap(builder))];
        }

        pub fn strtab(self: Index, builder: *const Builder) struct {
            offset: u32,
            size: u32,
        } {
            const name_index = self.name(builder).toIndex() orelse return .{
                .offset = 0,
                .size = 0,
            };

            return .{
                .offset = builder.strtab_string_indices.items[name_index],
                .size = builder.strtab_string_indices.items[name_index + 1] -
                    builder.strtab_string_indices.items[name_index],
            };
        }

        pub fn typeOf(self: Index, builder: *const Builder) Type {
            return self.ptrConst(builder).type;
        }

        pub fn toConst(global: Index) Constant {
            return @fromBackingInt(@intCast(@backingInt(Constant.first_global) + @backingInt(global)));
        }

        pub fn toValue(global: Index) Value {
            return global.toConst().toValue();
        }

        pub fn setLinkage(self: Index, linkage: Linkage, builder: *Builder) void {
            self.ptr(builder).linkage = linkage;
            self.updateDsoLocal(builder);
        }

        pub fn setVisibility(self: Index, visibility: Visibility, builder: *Builder) void {
            self.ptr(builder).visibility = visibility;
            self.updateDsoLocal(builder);
        }

        pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void {
            self.ptr(builder).dll_storage_class = class;
        }

        pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void {
            self.ptr(builder).unnamed_addr = unnamed_addr;
        }

        pub fn setDebugMetadata(self: Index, dbg: Metadata, builder: *Builder) void {
            self.ptr(builder).dbg = dbg.toOptional();
        }

        pub fn getDebugMetadata(self: Index, builder: *const Builder) Metadata.Optional {
            return self.ptrConst(builder).dbg;
        }

        const FormatData = struct {
            global: Index,
            builder: *const Builder,
        };
        fn format(data: FormatData, w: *Writer) Writer.Error!void {
            try w.print("@{f}", .{
                data.global.unwrap(data.builder).name(data.builder).fmt(data.builder, .quote_unless_valid_identifier),
            });
        }
        pub fn fmt(self: Index, builder: *const Builder) std.fmt.Alt(FormatData, format) {
            return .{ .data = .{ .global = self, .builder = builder } };
        }

        pub fn rename(self: Index, new_name: StrtabString, builder: *Builder) Allocator.Error!void {
            try builder.ensureUnusedGlobalCapacity(new_name);
            self.renameAssumeCapacity(new_name, builder);
        }

        pub fn takeName(self: Index, other: Index, builder: *Builder) Allocator.Error!void {
            try builder.ensureUnusedGlobalCapacity(.empty);
            self.takeNameAssumeCapacity(other, builder);
        }

        pub fn replace(self: Index, other: Index, builder: *Builder) Allocator.Error!void {
            try builder.ensureUnusedGlobalCapacity(.empty);
            self.replaceAssumeCapacity(other, builder);
        }

        pub fn delete(self: Index, builder: *Builder) void {
            self.ptr(builder).kind = .{ .replaced = .none };
        }

        /// Replaces whatever this `Global` currently contains with a new `Function`. Similar to
        /// `Builder.addFunction`, but the same `Global` is reused.
        pub fn toNewFunction(global: Index, builder: *Builder) Allocator.Error!Function.Index {
            try builder.functions.ensureUnusedCapacity(builder.gpa, 1);
            errdefer comptime unreachable;
            const function: Function.Index = @fromBackingInt(@intCast(builder.functions.items.len));
            builder.functions.appendAssumeCapacity(.{
                .global = global,
                .strip = undefined,
            });
            global.ptr(builder).kind = .{ .function = function };
            return function;
        }

        /// Replaces whatever this `Global` currently contains with a new `Variable`. Similar to
        /// `Builder.addVariable`, but the same `Global` is reused.
        pub fn toNewVariable(global: Index, builder: *Builder) Allocator.Error!Variable.Index {
            try builder.variables.ensureUnusedCapacity(builder.gpa, 1);
            errdefer comptime unreachable;
            const variable: Variable.Index = @fromBackingInt(@intCast(builder.variables.items.len));
            builder.variables.appendAssumeCapacity(.{ .global = global });
            global.ptr(builder).kind = .{ .variable = variable };
            return variable;
        }

        /// Replaces whatever this `Global` currently contains with a new `Alias`. Similar to
        /// `Builder.addAlias`, but the same `Global` is reused.
        pub fn toNewAlias(global: Index, builder: *Builder) Allocator.Error!Alias.Index {
            try builder.aliases.ensureUnusedCapacity(builder.gpa, 1);
            errdefer comptime unreachable;
            const alias: Alias.Index = @fromBackingInt(@intCast(builder.aliases.items.len));
            builder.aliass.appendAssumeCapacity(.{ .global = global, .aliasee = .none });
            global.ptr(builder).kind = .{ .alias = alias };
            return alias;
        }

        fn updateDsoLocal(self: Index, builder: *Builder) void {
            const self_ptr = self.ptr(builder);
            switch (self_ptr.linkage) {
                .private, .internal => {
                    self_ptr.visibility = .default;
                    self_ptr.dll_storage_class = .default;
                    self_ptr.preemption = .implicit_dso_local;
                },
                .extern_weak => if (self_ptr.preemption == .implicit_dso_local) {
                    self_ptr.preemption = .dso_local;
                },
                else => switch (self_ptr.visibility) {
                    .default => if (self_ptr.preemption == .implicit_dso_local) {
                        self_ptr.preemption = .dso_local;
                    },
                    else => self_ptr.preemption = .implicit_dso_local,
                },
            }
        }

        fn renameAssumeCapacity(self: Index, new_name: StrtabString, builder: *Builder) void {
            const old_name = self.name(builder);
            if (new_name == old_name) return;
            const index = @backingInt(self.unwrap(builder));
            _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]);
            builder.globals.swapRemoveAt(index);
            if (!old_name.isAnon()) return;
            builder.next_unnamed_global = @fromBackingInt(@intCast(@backingInt(builder.next_unnamed_global) - 1));
            if (builder.next_unnamed_global == old_name) return;
            builder.getGlobal(builder.next_unnamed_global).?.renameAssumeCapacity(old_name, builder);
        }

        fn takeNameAssumeCapacity(self: Index, other: Index, builder: *Builder) void {
            const other_name = other.name(builder);
            other.renameAssumeCapacity(.empty, builder);
            self.renameAssumeCapacity(other_name, builder);
        }

        fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void {
            if (self.eql(other, builder)) return;
            builder.next_replaced_global = @fromBackingInt(@intCast(@backingInt(builder.next_replaced_global) - 1));
            self.renameAssumeCapacity(builder.next_replaced_global, builder);
            self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };
        }
    };
}