enum FunctionAttributes [src]

Fields

none
_

Members

Source

pub const FunctionAttributes = enum(u32) { none, _, const function_index = 0; const return_index = 1; const params_index = 2; pub const Wip = struct { maps: Maps = .{}, const Map = std.AutoArrayHashMapUnmanaged(Attribute.Kind, Attribute.Index); const Maps = std.ArrayListUnmanaged(Map); pub fn deinit(self: *Wip, builder: *const Builder) void { for (self.maps.items) |*map| map.deinit(builder.gpa); self.maps.deinit(builder.gpa); self.* = undefined; } pub fn addFnAttr(self: *Wip, attribute: Attribute, builder: *Builder) Allocator.Error!void { try self.addAttr(function_index, attribute, builder); } pub fn addFnAttrIndex( self: *Wip, attribute_index: Attribute.Index, builder: *const Builder, ) Allocator.Error!void { try self.addAttrIndex(function_index, attribute_index, builder); } pub fn removeFnAttr(self: *Wip, attribute_kind: Attribute.Kind) Allocator.Error!bool { return self.removeAttr(function_index, attribute_kind); } pub fn addRetAttr(self: *Wip, attribute: Attribute, builder: *Builder) Allocator.Error!void { try self.addAttr(return_index, attribute, builder); } pub fn addRetAttrIndex( self: *Wip, attribute_index: Attribute.Index, builder: *const Builder, ) Allocator.Error!void { try self.addAttrIndex(return_index, attribute_index, builder); } pub fn removeRetAttr(self: *Wip, attribute_kind: Attribute.Kind) Allocator.Error!bool { return self.removeAttr(return_index, attribute_kind); } pub fn addParamAttr( self: *Wip, param_index: usize, attribute: Attribute, builder: *Builder, ) Allocator.Error!void { try self.addAttr(params_index + param_index, attribute, builder); } pub fn addParamAttrIndex( self: *Wip, param_index: usize, attribute_index: Attribute.Index, builder: *const Builder, ) Allocator.Error!void { try self.addAttrIndex(params_index + param_index, attribute_index, builder); } pub fn removeParamAttr( self: *Wip, param_index: usize, attribute_kind: Attribute.Kind, ) Allocator.Error!bool { return self.removeAttr(params_index + param_index, attribute_kind); } pub fn finish(self: *const Wip, builder: *Builder) Allocator.Error!FunctionAttributes { const attributes = try builder.gpa.alloc(Attributes, self.maps.items.len); defer builder.gpa.free(attributes); for (attributes, self.maps.items) |*attribute, map| attribute.* = try builder.attrs(map.values()); return builder.fnAttrs(attributes); } fn addAttr( self: *Wip, index: usize, attribute: Attribute, builder: *Builder, ) Allocator.Error!void { const map = try self.getOrPutMap(builder.gpa, index); try map.put(builder.gpa, attribute.getKind(), try builder.attr(attribute)); } fn addAttrIndex( self: *Wip, index: usize, attribute_index: Attribute.Index, builder: *const Builder, ) Allocator.Error!void { const map = try self.getOrPutMap(builder.gpa, index); try map.put(builder.gpa, attribute_index.getKind(builder), attribute_index); } fn removeAttr(self: *Wip, index: usize, attribute_kind: Attribute.Kind) Allocator.Error!bool { const map = self.getMap(index) orelse return false; return map.swapRemove(attribute_kind); } fn getOrPutMap(self: *Wip, allocator: Allocator, index: usize) Allocator.Error!*Map { if (index >= self.maps.items.len) try self.maps.appendNTimes(allocator, .{}, index + 1 - self.maps.items.len); return &self.maps.items[index]; } fn getMap(self: *Wip, index: usize) ?*Map { return if (index >= self.maps.items.len) null else &self.maps.items[index]; } fn ensureTotalLength(self: *Wip, new_len: usize) Allocator.Error!void { try self.maps.appendNTimes( .{}, std.math.sub(usize, new_len, self.maps.items.len) catch return, ); } }; pub fn func(self: FunctionAttributes, builder: *const Builder) Attributes { return self.get(function_index, builder); } pub fn ret(self: FunctionAttributes, builder: *const Builder) Attributes { return self.get(return_index, builder); } pub fn param(self: FunctionAttributes, param_index: usize, builder: *const Builder) Attributes { return self.get(params_index + param_index, builder); } pub fn toWip(self: FunctionAttributes, builder: *const Builder) Allocator.Error!Wip { var wip: Wip = .{}; errdefer wip.deinit(builder); const attributes_slice = self.slice(builder); try wip.maps.ensureTotalCapacityPrecise(builder.gpa, attributes_slice.len); for (attributes_slice) |attributes| { const map = wip.maps.addOneAssumeCapacity(); map.* = .{}; const attribute_slice = attributes.slice(builder); try map.ensureTotalCapacity(builder.gpa, attribute_slice.len); for (attributes.slice(builder)) |attribute| map.putAssumeCapacityNoClobber(attribute.getKind(builder), attribute); } return wip; } fn get(self: FunctionAttributes, index: usize, builder: *const Builder) Attributes { const attribute_slice = self.slice(builder); return if (index < attribute_slice.len) attribute_slice[index] else .none; } fn slice(self: FunctionAttributes, builder: *const Builder) []const Attributes { const start = builder.attributes_indices.items[@intFromEnum(self)]; const end = builder.attributes_indices.items[@intFromEnum(self) + 1]; return @ptrCast(builder.attributes_extra.items[start..end]); } }