union Attribute [src]
Fields
zeroext
signext
inreg
byval: Type
byref: Type
preallocated: Type
inalloca: Type
sret: Type
elementtype: Type
@"align": Alignment
@"noalias"
nocapture
nofree
nest
returned
nonnull
dereferenceable: u32
dereferenceable_or_null: u32
swiftself
swiftasync
swifterror
immarg
noundef
nofpclass: FpClass
alignstack: Alignment
allocalign
allocptr
readnone
readonly
writeonly
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
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
uwtable: UwTable
nocf_check
shadowcallstack
mustprogress
vscale_range: VScaleRange
no_sanitize_address
no_sanitize_hwaddress
sanitize_address_dyninit
string: struct { kind: String, value: String }
none: noreturn
Members
Source
pub const Attribute = union(Kind) {
// Parameter Attributes
zeroext,
signext,
inreg,
byval: Type,
byref: Type,
preallocated: Type,
inalloca: Type,
sret: Type,
elementtype: Type,
@"align": Alignment,
@"noalias",
nocapture,
nofree,
nest,
returned,
nonnull,
dereferenceable: u32,
dereferenceable_or_null: u32,
swiftself,
swiftasync,
swifterror,
immarg,
noundef,
nofpclass: FpClass,
alignstack: Alignment,
allocalign,
allocptr,
readnone,
readonly,
writeonly,
// Function Attributes
//alignstack: Alignment,
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 = @enumFromInt(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 = comptime blk: {
@setEvalBranchQuota(10_000);
for (@typeInfo(Attribute).@"union".fields) |field| {
if (std.mem.eql(u8, field.name, @tagName(kind))) break :blk field;
}
unreachable;
};
comptime assert(std.mem.eql(u8, @tagName(kind), field.name));
return @unionInit(Attribute, field.name, switch (field.type) {
void => {},
u32 => storage.value,
Alignment, String, Type, UwTable => @enumFromInt(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,
};
fn format(
data: FormatData,
comptime fmt_str: []const u8,
_: std.fmt.FormatOptions,
writer: anytype,
) @TypeOf(writer).Error!void {
if (comptime std.mem.indexOfNone(u8, fmt_str, "\"#")) |_|
@compileError("invalid format string: '" ++ fmt_str ++ "'");
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 writer.print(" {s}", .{@tagName(attribute)}),
.byval,
.byref,
.preallocated,
.inalloca,
.sret,
.elementtype,
=> |ty| try writer.print(" {s}({%})", .{ @tagName(attribute), ty.fmt(data.builder) }),
.@"align" => |alignment| try writer.print("{ }", .{alignment}),
.dereferenceable,
.dereferenceable_or_null,
=> |size| try writer.print(" {s}({d})", .{ @tagName(attribute), size }),
.nofpclass => |fpclass| {
const Int = @typeInfo(FpClass).@"struct".backing_integer.?;
try writer.print(" {s}(", .{@tagName(attribute)});
var any = false;
var remaining: Int = @bitCast(fpclass);
inline for (@typeInfo(FpClass).@"struct".decls) |decl| {
const pattern: Int = @bitCast(@field(FpClass, decl.name));
if (remaining & pattern == pattern) {
if (!any) {
try writer.writeByte(' ');
any = true;
}
try writer.writeAll(decl.name);
remaining &= ~pattern;
}
}
try writer.writeByte(')');
},
.alignstack => |alignment| try writer.print(
if (comptime std.mem.indexOfScalar(u8, fmt_str, '#') != null)
" {s}={d}"
else
" {s}({d})",
.{ @tagName(attribute), alignment.toByteUnits() orelse return },
),
.allockind => |allockind| {
try writer.print(" {s}(\"", .{@tagName(attribute)});
var any = false;
inline for (@typeInfo(AllocKind).@"struct".fields) |field| {
if (comptime std.mem.eql(u8, field.name, "_")) continue;
if (@field(allockind, field.name)) {
if (!any) {
try writer.writeByte(',');
any = true;
}
try writer.writeAll(field.name);
}
}
try writer.writeAll("\")");
},
.allocsize => |allocsize| {
try writer.print(" {s}({d}", .{ @tagName(attribute), allocsize.elem_size });
if (allocsize.num_elems != AllocSize.none)
try writer.print(",{d}", .{allocsize.num_elems});
try writer.writeByte(')');
},
.memory => |memory| {
try writer.print(" {s}(", .{@tagName(attribute)});
var any = memory.other != .none or
(memory.argmem == .none and memory.inaccessiblemem == .none);
if (any) try writer.writeAll(@tagName(memory.other));
inline for (.{ "argmem", "inaccessiblemem" }) |kind| {
if (@field(memory, kind) != memory.other) {
if (any) try writer.writeAll(", ");
try writer.print("{s}: {s}", .{ kind, @tagName(@field(memory, kind)) });
any = true;
}
}
try writer.writeByte(')');
},
.uwtable => |uwtable| if (uwtable != .none) {
try writer.print(" {s}", .{@tagName(attribute)});
if (uwtable != UwTable.default) try writer.print("({s})", .{@tagName(uwtable)});
},
.vscale_range => |vscale_range| try writer.print(" {s}({d},{d})", .{
@tagName(attribute),
vscale_range.min.toByteUnits().?,
vscale_range.max.toByteUnits() orelse 0,
}),
.string => |string_attr| if (comptime std.mem.indexOfScalar(u8, fmt_str, '"') != null) {
try writer.print(" {\"}", .{string_attr.kind.fmt(data.builder)});
if (string_attr.value != .empty)
try writer.print("={\"}", .{string_attr.value.fmt(data.builder)});
},
.none => unreachable,
}
}
pub fn fmt(self: Index, builder: *const Builder) std.fmt.Formatter(format) {
return .{ .data = .{ .attribute_index = self, .builder = builder } };
}
fn toStorage(self: Index, builder: *const Builder) Storage {
return builder.attributes.keys()[@intFromEnum(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 = std.math.maxInt(u31),
none = std.math.maxInt(u32),
_,
pub const len = @typeInfo(Kind).@"enum".fields.len - 2;
pub fn fromString(str: String) Kind {
assert(!str.isAnon());
const kind: Kind = @enumFromInt(@intFromEnum(str));
assert(kind != .none);
return kind;
}
fn toString(self: Kind) ?String {
assert(self != .none);
const str: String = @enumFromInt(@intFromEnum(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 = std.math.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 => std.math.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, String, Type, UwTable => @intFromEnum(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 = @intFromEnum(string_attr.value),
},
.none => unreachable,
};
}
}