struct Global [src]
Fields
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 = .none
kind: union(enum) {
alias: Alias.Index,
variable: Variable.Index,
function: Function.Index,
replaced: Global.Index,
}
Members
- Index (enum)
Source
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 = .none,
kind: union(enum) {
alias: Alias.Index,
variable: Variable.Index,
function: Function.Index,
replaced: Global.Index,
},
pub const Index = enum(u32) {
none = std.math.maxInt(u32),
_,
pub fn unwrap(self: Index, builder: *const Builder) Index {
var cur = self;
while (true) {
const replacement = cur.getReplacement(builder);
if (replacement == .none) return cur;
cur = replacement;
}
}
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()[@intFromEnum(self.unwrap(builder))];
}
pub fn ptrConst(self: Index, builder: *const Builder) *const Global {
return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];
}
pub fn name(self: Index, builder: *const Builder) StrtabString {
return builder.globals.keys()[@intFromEnum(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(self: Index) Constant {
return @enumFromInt(@intFromEnum(Constant.first_global) + @intFromEnum(self));
}
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;
}
const FormatData = struct {
global: Index,
builder: *const Builder,
};
fn format(
data: FormatData,
comptime _: []const u8,
_: std.fmt.FormatOptions,
writer: anytype,
) @TypeOf(writer).Error!void {
try writer.print("@{}", .{
data.global.unwrap(data.builder).name(data.builder).fmt(data.builder),
});
}
pub fn fmt(self: Index, builder: *const Builder) std.fmt.Formatter(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 };
}
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 = @intFromEnum(self.unwrap(builder));
_ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]);
builder.globals.swapRemoveAt(index);
if (!old_name.isAnon()) return;
builder.next_unnamed_global = @enumFromInt(@intFromEnum(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 = @enumFromInt(@intFromEnum(builder.next_replaced_global) - 1);
self.renameAssumeCapacity(builder.next_replaced_global, builder);
self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) };
}
fn getReplacement(self: Index, builder: *const Builder) Index {
return switch (builder.globals.values()[@intFromEnum(self)].kind) {
.replaced => |replacement| replacement,
else => .none,
};
}
};
}