diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index dd8bb6605b..15e7891d18 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -311,8 +311,8 @@ pub const Type = enum(u32) { .function, .vararg_function, => { - const extra = builder.typeExtraDataTrail(Type.Function, item.data); - return @ptrCast(builder.type_extra.items[extra.end..][0..extra.data.params_len]); + var extra = builder.typeExtraDataTrail(Type.Function, item.data); + return extra.trail.next(extra.data.params_len, Type, builder); }, else => unreachable, } @@ -519,8 +519,8 @@ pub const Type = enum(u32) { .structure, .packed_structure, => { - const extra = builder.typeExtraDataTrail(Type.Structure, item.data); - return @ptrCast(builder.type_extra.items[extra.end..][0..extra.data.fields_len]); + var extra = builder.typeExtraDataTrail(Type.Structure, item.data); + return extra.trail.next(extra.data.fields_len, Type, builder); }, .named_structure => return builder.typeExtraData(Type.NamedStructure, item.data).body .structFields(builder), @@ -539,9 +539,8 @@ pub const Type = enum(u32) { .structure, .packed_structure, => { - const extra = builder.typeExtraDataTrail(Type.Structure, item.data); - const fields: []const Type = - @ptrCast(builder.type_extra.items[extra.end..][0..extra.data.fields_len]); + var extra = builder.typeExtraDataTrail(Type.Structure, item.data); + const fields = extra.trail.next(extra.data.fields_len, Type, builder); return fields[indices[0]].childTypeAt(indices[1..], builder); }, .named_structure => builder.typeExtraData(Type.NamedStructure, item.data).body @@ -590,9 +589,8 @@ pub const Type = enum(u32) { .metadata => "Metadata", }), .function, .vararg_function => |kind| { - const extra = data.builder.typeExtraDataTrail(Type.Function, item.data); - const params: []const Type = - @ptrCast(data.builder.type_extra.items[extra.end..][0..extra.data.params_len]); + var extra = data.builder.typeExtraDataTrail(Type.Function, item.data); + const params = extra.trail.next(extra.data.params_len, Type, data.builder); try writer.print("f_{m}", .{extra.data.ret.fmt(data.builder)}); for (params) |param| try writer.print("{m}", .{param.fmt(data.builder)}); switch (kind) { @@ -605,11 +603,9 @@ pub const Type = enum(u32) { .integer => try writer.print("i{d}", .{item.data}), .pointer => try writer.print("p{d}", .{item.data}), .target => { - const extra = data.builder.typeExtraDataTrail(Type.Target, item.data); - const types: []const Type = - @ptrCast(data.builder.type_extra.items[extra.end..][0..extra.data.types_len]); - const ints: []const u32 = @ptrCast(data.builder.type_extra.items[extra.end + - extra.data.types_len ..][0..extra.data.ints_len]); + var extra = data.builder.typeExtraDataTrail(Type.Target, item.data); + const types = extra.trail.next(extra.data.types_len, Type, data.builder); + const ints = extra.trail.next(extra.data.ints_len, u32, data.builder); try writer.print("t{s}", .{extra.data.name.toSlice(data.builder).?}); for (types) |ty| try writer.print("_{m}", .{ty.fmt(data.builder)}); for (ints) |int| try writer.print("_{d}", .{int}); @@ -636,9 +632,8 @@ pub const Type = enum(u32) { try writer.print("a{d}{m}", .{ extra.length(), extra.child.fmt(data.builder) }); }, .structure, .packed_structure => { - const extra = data.builder.typeExtraDataTrail(Type.Structure, item.data); - const fields: []const Type = - @ptrCast(data.builder.type_extra.items[extra.end..][0..extra.data.fields_len]); + var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data); + const fields = extra.trail.next(extra.data.fields_len, Type, data.builder); try writer.writeAll("sl_"); for (fields) |field| try writer.print("{m}", .{field.fmt(data.builder)}); try writer.writeByte('s'); @@ -656,9 +651,8 @@ pub const Type = enum(u32) { switch (item.tag) { .simple => unreachable, .function, .vararg_function => |kind| { - const extra = data.builder.typeExtraDataTrail(Type.Function, item.data); - const params: []const Type = - @ptrCast(data.builder.type_extra.items[extra.end..][0..extra.data.params_len]); + var extra = data.builder.typeExtraDataTrail(Type.Function, item.data); + const params = extra.trail.next(extra.data.params_len, Type, data.builder); if (!comptime std.mem.eql(u8, fmt_str, ">")) try writer.print("{%} ", .{extra.data.ret.fmt(data.builder)}); if (!comptime std.mem.eql(u8, fmt_str, "<")) { @@ -681,11 +675,9 @@ pub const Type = enum(u32) { .integer => try writer.print("i{d}", .{item.data}), .pointer => try writer.print("ptr{}", .{@as(AddrSpace, @enumFromInt(item.data))}), .target => { - const extra = data.builder.typeExtraDataTrail(Type.Target, item.data); - const types: []const Type = - @ptrCast(data.builder.type_extra.items[extra.end..][0..extra.data.types_len]); - const ints: []const u32 = @ptrCast(data.builder.type_extra.items[extra.end + - extra.data.types_len ..][0..extra.data.ints_len]); + var extra = data.builder.typeExtraDataTrail(Type.Target, item.data); + const types = extra.trail.next(extra.data.types_len, Type, data.builder); + const ints = extra.trail.next(extra.data.ints_len, u32, data.builder); try writer.print( \\target({"} , .{extra.data.name.fmt(data.builder)}); @@ -714,9 +706,8 @@ pub const Type = enum(u32) { try writer.print("[{d} x {%}]", .{ extra.length(), extra.child.fmt(data.builder) }); }, .structure, .packed_structure => |kind| { - const extra = data.builder.typeExtraDataTrail(Type.Structure, item.data); - const fields: []const Type = - @ptrCast(data.builder.type_extra.items[extra.end..][0..extra.data.fields_len]); + var extra = data.builder.typeExtraDataTrail(Type.Structure, item.data); + const fields = extra.trail.next(extra.data.fields_len, Type, data.builder); switch (kind) { .structure => {}, .packed_structure => try writer.writeByte('<'), @@ -812,10 +803,8 @@ pub const Type = enum(u32) { => { if (try visited.fetchPut(builder.gpa, self, {})) |_| return false; - const extra = builder.typeExtraDataTrail(Type.Structure, item.data); - const fields: []const Type = @ptrCast( - builder.type_extra.items[extra.end..][0..extra.data.fields_len], - ); + var extra = builder.typeExtraDataTrail(Type.Structure, item.data); + const fields = extra.trail.next(extra.data.fields_len, Type, builder); for (fields) |field| { if (field.isVector(builder) and field.vectorKind(builder) == .scalable) return false; @@ -1639,9 +1628,8 @@ pub const Function = struct { .extractelement => wip.extraData(ExtractElement, instruction.data) .val.typeOfWip(wip).childType(wip.builder), .extractvalue => { - const extra = wip.extraDataTrail(ExtractValue, instruction.data); - const indices: []const u32 = - wip.extra.items[extra.end..][0..extra.data.indices_len]; + var extra = wip.extraDataTrail(ExtractValue, instruction.data); + const indices = extra.trail.next(extra.data.indices_len, u32, wip); return extra.data.val.typeOfWip(wip).childTypeAt(indices, wip.builder); }, .@"fcmp false", @@ -1694,9 +1682,8 @@ pub const Function = struct { .getelementptr, .@"getelementptr inbounds", => { - const extra = wip.extraDataTrail(GetElementPtr, instruction.data); - const indices: []const Value = - @ptrCast(wip.extra.items[extra.end..][0..extra.data.indices_len]); + var extra = wip.extraDataTrail(GetElementPtr, instruction.data); + const indices = extra.trail.next(extra.data.indices_len, Value, wip); const base_ty = extra.data.base.typeOfWip(wip); if (!base_ty.isVector(wip.builder)) for (indices) |index| { const index_ty = index.typeOfWip(wip); @@ -1829,9 +1816,8 @@ pub const Function = struct { .extractelement => function.extraData(ExtractElement, instruction.data) .val.typeOf(function_index, builder).childType(builder), .extractvalue => { - const extra = function.extraDataTrail(ExtractValue, instruction.data); - const indices: []const u32 = - function.extra[extra.end..][0..extra.data.indices_len]; + var extra = function.extraDataTrail(ExtractValue, instruction.data); + const indices = extra.trail.next(extra.data.indices_len, u32, function); return extra.data.val.typeOf(function_index, builder) .childTypeAt(indices, builder); }, @@ -1885,9 +1871,8 @@ pub const Function = struct { .getelementptr, .@"getelementptr inbounds", => { - const extra = function.extraDataTrail(GetElementPtr, instruction.data); - const indices: []const Value = - @ptrCast(function.extra[extra.end..][0..extra.data.indices_len]); + var extra = function.extraDataTrail(GetElementPtr, instruction.data); + const indices = extra.trail.next(extra.data.indices_len, Value, function); const base_ty = extra.data.base.typeOf(function_index, builder); if (!base_ty.isVector(builder)) for (indices) |index| { const index_ty = index.typeOf(function_index, builder); @@ -1908,10 +1893,9 @@ pub const Function = struct { .phi, .@"phi fast", => { - const extra = function.extraDataTrail(Phi, instruction.data); - const incoming_vals: []const Value = - @ptrCast(function.extra[extra.end..][0..extra.data.incoming_len]); - return incoming_vals[0].typeOf(function_index, builder); + var extra = function.extraDataTrail(Phi, instruction.data); + const vals = extra.trail.next(extra.data.incoming_len, Value, function); + return vals[0].typeOf(function_index, builder); }, .select, .@"select fast", @@ -2112,11 +2096,32 @@ pub const Function = struct { return argument_index.toValue(); } + const ExtraDataTrail = struct { + index: Instruction.ExtraIndex, + + fn nextMut(self: *ExtraDataTrail, len: u32, comptime Item: type, function: *Function) []Item { + const items: []Item = @ptrCast(function.extra[self.index..][0..len]); + self.index += @intCast(len); + return items; + } + + fn next( + self: *ExtraDataTrail, + len: u32, + comptime Item: type, + function: *const Function, + ) []const Item { + const items: []const Item = @ptrCast(function.extra[self.index..][0..len]); + self.index += @intCast(len); + return items; + } + }; + fn extraDataTrail( self: *const Function, comptime T: type, index: Instruction.ExtraIndex, - ) struct { data: T, end: Instruction.ExtraIndex } { + ) struct { data: T, trail: ExtraDataTrail } { var result: T = undefined; const fields = @typeInfo(T).Struct.fields; inline for (fields, self.extra[index..][0..fields.len]) |field, value| @@ -2126,7 +2131,10 @@ pub const Function = struct { MemoryAccessInfo, Instruction.Alloca.Info => @bitCast(value), else => @compileError("bad field type: " ++ @typeName(field.type)), }; - return .{ .data = result, .end = index + @as(Type.Item.ExtraIndex, @intCast(fields.len)) }; + return .{ + .data = result, + .trail = .{ .index = index + @as(Type.Item.ExtraIndex, @intCast(fields.len)) }, + }; } fn extraData(self: *const Function, comptime T: type, index: Instruction.ExtraIndex) T { @@ -2315,14 +2323,10 @@ pub const WipFunction = struct { wip: *WipFunction, ) Allocator.Error!void { const instruction = wip.instructions.get(@intFromEnum(self.instruction)); - const extra = wip.extraDataTrail(Instruction.Switch, instruction.data); - const case_vals: []Constant = - @ptrCast(wip.extra.items[extra.end..][0..extra.data.cases_len]); - const case_dests: []Block.Index = - @ptrCast(wip.extra.items[extra.end + extra.data.cases_len ..][0..extra.data.cases_len]); + var extra = wip.extraDataTrail(Instruction.Switch, instruction.data); assert(val.typeOf(wip.builder) == extra.data.val.typeOfWip(wip)); - case_vals[self.index] = val; - case_dests[self.index] = dest; + extra.trail.nextMut(extra.data.cases_len, Constant, wip)[self.index] = val; + extra.trail.nextMut(extra.data.cases_len, Block.Index, wip)[self.index] = dest; self.index += 1; dest.ptr(wip).branches += 1; if (wip.builder.useLibLlvm()) @@ -3113,13 +3117,10 @@ pub const WipFunction = struct { const incoming_len = self.block.ptrConst(wip).incoming; assert(vals.len == incoming_len and blocks.len == incoming_len); const instruction = wip.instructions.get(@intFromEnum(self.instruction)); - const extra = wip.extraDataTrail(Instruction.WipPhi, instruction.data); + var extra = wip.extraDataTrail(Instruction.WipPhi, instruction.data); for (vals) |val| assert(val.typeOfWip(wip) == extra.data.type); - const incoming_vals: []Value = @ptrCast(wip.extra.items[extra.end..][0..incoming_len]); - const incoming_blocks: []Block.Index = - @ptrCast(wip.extra.items[extra.end + incoming_len ..][0..incoming_len]); - @memcpy(incoming_vals, vals); - @memcpy(incoming_blocks, blocks); + @memcpy(extra.trail.nextMut(incoming_len, Value, wip), vals); + @memcpy(extra.trail.nextMut(incoming_len, Block.Index, wip), blocks); if (wip.builder.useLibLlvm()) { const ExpectedContents = extern struct { [expected_incoming_len]*llvm.Value, @@ -3504,9 +3505,8 @@ pub const WipFunction = struct { }); }, .extractvalue => { - const extra = self.extraDataTrail(Instruction.ExtractValue, instruction.data); - const indices: []const u32 = - self.extra.items[extra.end..][0..extra.data.indices_len]; + var extra = self.extraDataTrail(Instruction.ExtractValue, instruction.data); + const indices = extra.trail.next(extra.data.indices_len, u32, self); instruction.data = wip_extra.addExtra(Instruction.ExtractValue{ .val = instructions.map(extra.data.val), .indices_len = extra.data.indices_len, @@ -3520,9 +3520,8 @@ pub const WipFunction = struct { .getelementptr, .@"getelementptr inbounds", => { - const extra = self.extraDataTrail(Instruction.GetElementPtr, instruction.data); - const indices: []const Value = - @ptrCast(self.extra.items[extra.end..][0..extra.data.indices_len]); + var extra = self.extraDataTrail(Instruction.GetElementPtr, instruction.data); + const indices = extra.trail.next(extra.data.indices_len, Value, self); instruction.data = wip_extra.addExtra(Instruction.GetElementPtr{ .type = extra.data.type, .base = instructions.map(extra.data.base), @@ -3539,9 +3538,8 @@ pub const WipFunction = struct { }); }, .insertvalue => { - const extra = self.extraDataTrail(Instruction.InsertValue, instruction.data); - const indices: []const u32 = - self.extra.items[extra.end..][0..extra.data.indices_len]; + var extra = self.extraDataTrail(Instruction.InsertValue, instruction.data); + const indices = extra.trail.next(extra.data.indices_len, u32, self); instruction.data = wip_extra.addExtra(Instruction.InsertValue{ .val = instructions.map(extra.data.val), .elem = instructions.map(extra.data.elem), @@ -3564,12 +3562,10 @@ pub const WipFunction = struct { .phi, .@"phi fast", => { - const extra = self.extraDataTrail(Instruction.WipPhi, instruction.data); const incoming_len = current_block.incoming; - const incoming_vals: []const Value = - @ptrCast(self.extra.items[extra.end..][0..incoming_len]); - const incoming_blocks: []const Block.Index = - @ptrCast(self.extra.items[extra.end + incoming_len ..][0..incoming_len]); + var extra = self.extraDataTrail(Instruction.WipPhi, instruction.data); + const incoming_vals = extra.trail.next(incoming_len, Value, self); + const incoming_blocks = extra.trail.next(incoming_len, Block.Index, self); instruction.data = wip_extra.addExtra(Instruction.Phi{ .incoming_len = incoming_len, }); @@ -3607,11 +3603,9 @@ pub const WipFunction = struct { }); }, .@"switch" => { - const extra = self.extraDataTrail(Instruction.Switch, instruction.data); - const case_vals: []const Constant = - @ptrCast(self.extra.items[extra.end..][0..extra.data.cases_len]); - const case_blocks: []const Block.Index = @ptrCast(self.extra - .items[extra.end + extra.data.cases_len ..][0..extra.data.cases_len]); + var extra = self.extraDataTrail(Instruction.Switch, instruction.data); + const case_vals = extra.trail.next(extra.data.cases_len, Constant, self); + const case_blocks = extra.trail.next(extra.data.cases_len, Block.Index, self); instruction.data = wip_extra.addExtra(Instruction.Switch{ .val = instructions.map(extra.data.val), .default = extra.data.default, @@ -3956,11 +3950,32 @@ pub const WipFunction = struct { return result; } + const ExtraDataTrail = struct { + index: Instruction.ExtraIndex, + + fn nextMut(self: *ExtraDataTrail, len: u32, comptime Item: type, wip: *WipFunction) []Item { + const items: []Item = @ptrCast(wip.extra.items[self.index..][0..len]); + self.index += @intCast(len); + return items; + } + + fn next( + self: *ExtraDataTrail, + len: u32, + comptime Item: type, + wip: *const WipFunction, + ) []const Item { + const items: []const Item = @ptrCast(wip.extra.items[self.index..][0..len]); + self.index += @intCast(len); + return items; + } + }; + fn extraDataTrail( self: *const WipFunction, comptime T: type, index: Instruction.ExtraIndex, - ) struct { data: T, end: Instruction.ExtraIndex } { + ) struct { data: T, trail: ExtraDataTrail } { var result: T = undefined; const fields = @typeInfo(T).Struct.fields; inline for (fields, self.extra.items[index..][0..fields.len]) |field, value| @@ -3970,7 +3985,10 @@ pub const WipFunction = struct { MemoryAccessInfo, Instruction.Alloca.Info => @bitCast(value), else => @compileError("bad field type: " ++ @typeName(field.type)), }; - return .{ .data = result, .end = index + @as(Type.Item.ExtraIndex, @intCast(fields.len)) }; + return .{ + .data = result, + .trail = .{ .index = index + @as(Type.Item.ExtraIndex, @intCast(fields.len)) }, + }; } fn extraData(self: *const WipFunction, comptime T: type, index: Instruction.ExtraIndex) T { @@ -4315,9 +4333,9 @@ pub const Constant = enum(u32) { .getelementptr, .@"getelementptr inbounds", => { - const extra = builder.constantExtraDataTrail(GetElementPtr, item.data); - const indices: []const Constant = @ptrCast(builder.constant_extra - .items[extra.end..][0..extra.data.info.indices_len]); + var extra = builder.constantExtraDataTrail(GetElementPtr, item.data); + const indices = + extra.trail.next(extra.data.info.indices_len, Constant, builder); const base_ty = extra.data.base.typeOf(builder); if (!base_ty.isVector(builder)) for (indices) |index| { const index_ty = index.typeOf(builder); @@ -4392,10 +4410,9 @@ pub const Constant = enum(u32) { return extra.lo_lo == 0 and extra.lo_hi == 0 and extra.hi == 0; }, .vector => { - const extra = builder.constantExtraDataTrail(Aggregate, item.data); - const len = extra.data.type.aggregateLen(builder); - const vals: []const Constant = - @ptrCast(builder.constant_extra.items[extra.end..][0..len]); + var extra = builder.constantExtraDataTrail(Aggregate, item.data); + const len: u32 = @intCast(extra.data.type.aggregateLen(builder)); + const vals = extra.trail.next(len, Constant, builder); for (vals) |val| if (!val.isZeroInit(builder)) return false; return true; }, @@ -4549,10 +4566,9 @@ pub const Constant = enum(u32) { .array, .vector, => |tag| { - const extra = data.builder.constantExtraDataTrail(Aggregate, item.data); - const len = extra.data.type.aggregateLen(data.builder); - const vals: []const Constant = - @ptrCast(data.builder.constant_extra.items[extra.end..][0..len]); + var extra = data.builder.constantExtraDataTrail(Aggregate, item.data); + const len: u32 = @intCast(extra.data.type.aggregateLen(data.builder)); + const vals = extra.trail.next(len, Constant, data.builder); try writer.writeAll(switch (tag) { .structure => "{ ", .packed_structure => "<{ ", @@ -4631,9 +4647,9 @@ pub const Constant = enum(u32) { .getelementptr, .@"getelementptr inbounds", => |tag| { - const extra = data.builder.constantExtraDataTrail(GetElementPtr, item.data); - const indices: []const Constant = @ptrCast(data.builder.constant_extra - .items[extra.end..][0..extra.data.info.indices_len]); + var extra = data.builder.constantExtraDataTrail(GetElementPtr, item.data); + const indices = + extra.trail.next(extra.data.info.indices_len, Constant, data.builder); try writer.print("{s} ({%}, {%}", .{ @tagName(tag), extra.data.type.fmt(data.builder), @@ -5243,9 +5259,8 @@ pub fn namedTypeSetBody( @intFromEnum(body_type); if (self.useLibLlvm()) { const body_item = self.type_items.items[@intFromEnum(body_type)]; - const body_extra = self.typeExtraDataTrail(Type.Structure, body_item.data); - const body_fields: []const Type = - @ptrCast(self.type_extra.items[body_extra.end..][0..body_extra.data.fields_len]); + var body_extra = self.typeExtraDataTrail(Type.Structure, body_item.data); + const body_fields = body_extra.trail.next(body_extra.data.fields_len, Type, self); const llvm_fields = try self.gpa.alloc(*llvm.Type, body_fields.len); defer self.gpa.free(llvm_fields); for (llvm_fields, body_fields) |*llvm_field, body_field| llvm_field.* = body_field.toLlvm(self); @@ -5947,10 +5962,9 @@ pub fn dump(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocator }); }, .extractvalue => |tag| { - const extra = + var extra = function.extraDataTrail(Function.Instruction.ExtractValue, instruction.data); - const indices: []const u32 = - function.extra[extra.end..][0..extra.data.indices_len]; + const indices = extra.trail.next(extra.data.indices_len, u32, &function); try writer.print(" %{} = {s} {%}", .{ instruction_index.name(&function).fmt(self), @tagName(tag), @@ -5976,12 +5990,11 @@ pub fn dump(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocator .getelementptr, .@"getelementptr inbounds", => |tag| { - const extra = function.extraDataTrail( + var extra = function.extraDataTrail( Function.Instruction.GetElementPtr, instruction.data, ); - const indices: []const Value = - @ptrCast(function.extra[extra.end..][0..extra.data.indices_len]); + const indices = extra.trail.next(extra.data.indices_len, Value, &function); try writer.print(" %{} = {s} {%}, {%}", .{ instruction_index.name(&function).fmt(self), @tagName(tag), @@ -6005,10 +6018,9 @@ pub fn dump(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocator }); }, .insertvalue => |tag| { - const extra = + var extra = function.extraDataTrail(Function.Instruction.InsertValue, instruction.data); - const indices: []const u32 = - function.extra[extra.end..][0..extra.data.indices_len]; + const indices = extra.trail.next(extra.data.indices_len, u32, &function); try writer.print(" %{} = {s} {%}, {%}", .{ instruction_index.name(&function).fmt(self), @tagName(tag), @@ -6063,12 +6075,10 @@ pub fn dump(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocator .phi, .@"phi fast", => |tag| { - const extra = - function.extraDataTrail(Function.Instruction.Phi, instruction.data); - const vals: []const Value = - @ptrCast(function.extra[extra.end..][0..extra.data.incoming_len]); - const blocks: []const Function.Block.Index = @ptrCast(function.extra[extra.end + - extra.data.incoming_len ..][0..extra.data.incoming_len]); + var extra = function.extraDataTrail(Function.Instruction.Phi, instruction.data); + const vals = extra.trail.next(extra.data.incoming_len, Value, &function); + const blocks = + extra.trail.next(extra.data.incoming_len, Function.Block.Index, &function); try writer.print(" %{} = {s} {%} ", .{ instruction_index.name(&function).fmt(self), @tagName(tag), @@ -6125,12 +6135,11 @@ pub fn dump(self: *Builder, writer: anytype) (@TypeOf(writer).Error || Allocator }); }, .@"switch" => |tag| { - const extra = + var extra = function.extraDataTrail(Function.Instruction.Switch, instruction.data); - const vals: []const Constant = - @ptrCast(function.extra[extra.end..][0..extra.data.cases_len]); - const blocks: []const Function.Block.Index = @ptrCast(function.extra[extra.end + - extra.data.cases_len ..][0..extra.data.cases_len]); + const vals = extra.trail.next(extra.data.cases_len, Constant, &function); + const blocks = + extra.trail.next(extra.data.cases_len, Function.Block.Index, &function); try writer.print(" {s} {%}, {%} [", .{ @tagName(tag), extra.data.val.fmt(function_index, self), @@ -6216,9 +6225,8 @@ fn fnTypeAssumeCapacity( } pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { const rhs_data = ctx.builder.type_items.items[rhs_index]; - const rhs_extra = ctx.builder.typeExtraDataTrail(Type.Function, rhs_data.data); - const rhs_params: []const Type = - @ptrCast(ctx.builder.type_extra.items[rhs_extra.end..][0..rhs_extra.data.params_len]); + var rhs_extra = ctx.builder.typeExtraDataTrail(Type.Function, rhs_data.data); + const rhs_params = rhs_extra.trail.next(rhs_extra.data.params_len, Type, ctx.builder); return rhs_data.tag == tag and lhs_key.ret == rhs_extra.data.ret and std.mem.eql(Type, lhs_key.params, rhs_params); } @@ -6400,9 +6408,8 @@ fn structTypeAssumeCapacity( } pub fn eql(ctx: @This(), lhs_key: []const Type, _: void, rhs_index: usize) bool { const rhs_data = ctx.builder.type_items.items[rhs_index]; - const rhs_extra = ctx.builder.typeExtraDataTrail(Type.Structure, rhs_data.data); - const rhs_fields: []const Type = - @ptrCast(ctx.builder.type_extra.items[rhs_extra.end..][0..rhs_extra.data.fields_len]); + var rhs_extra = ctx.builder.typeExtraDataTrail(Type.Structure, rhs_data.data); + const rhs_fields = rhs_extra.trail.next(rhs_extra.data.fields_len, Type, ctx.builder); return rhs_data.tag == tag and std.mem.eql(Type, lhs_key, rhs_fields); } }; @@ -6542,11 +6549,32 @@ fn addTypeExtraAssumeCapacity(self: *Builder, extra: anytype) Type.Item.ExtraInd return result; } +const TypeExtraDataTrail = struct { + index: Type.Item.ExtraIndex, + + fn nextMut(self: *TypeExtraDataTrail, len: u32, comptime Item: type, builder: *Builder) []Item { + const items: []Item = @ptrCast(builder.type_extra.items[self.index..][0..len]); + self.index += @intCast(len); + return items; + } + + fn next( + self: *TypeExtraDataTrail, + len: u32, + comptime Item: type, + builder: *const Builder, + ) []const Item { + const items: []const Item = @ptrCast(builder.type_extra.items[self.index..][0..len]); + self.index += @intCast(len); + return items; + } +}; + fn typeExtraDataTrail( self: *const Builder, comptime T: type, index: Type.Item.ExtraIndex, -) struct { data: T, end: Type.Item.ExtraIndex } { +) struct { data: T, trail: TypeExtraDataTrail } { var result: T = undefined; const fields = @typeInfo(T).Struct.fields; inline for (fields, self.type_extra.items[index..][0..fields.len]) |field, value| @@ -6555,7 +6583,10 @@ fn typeExtraDataTrail( String, Type => @enumFromInt(value), else => @compileError("bad field type: " ++ @typeName(field.type)), }; - return .{ .data = result, .end = index + @as(Type.Item.ExtraIndex, @intCast(fields.len)) }; + return .{ + .data = result, + .trail = .{ .index = index + @as(Type.Item.ExtraIndex, @intCast(fields.len)) }, + }; } fn typeExtraData(self: *const Builder, comptime T: type, index: Type.Item.ExtraIndex) T { @@ -6914,7 +6945,7 @@ fn structConstAssumeCapacity( vals: []const Constant, ) if (build_options.have_llvm) Allocator.Error!Constant else Constant { const type_item = self.type_items.items[@intFromEnum(ty)]; - const extra = self.typeExtraDataTrail(Type.Structure, switch (type_item.tag) { + var extra = self.typeExtraDataTrail(Type.Structure, switch (type_item.tag) { .structure, .packed_structure => type_item.data, .named_structure => data: { const body_ty = self.typeExtraData(Type.NamedStructure, type_item.data).body; @@ -6926,8 +6957,7 @@ fn structConstAssumeCapacity( }, else => unreachable, }); - const fields: []const Type = - @ptrCast(self.type_extra.items[extra.end..][0..extra.data.fields_len]); + const fields = extra.trail.next(extra.data.fields_len, Type, self); for (fields, vals) |field, val| assert(field == val.typeOf(self)); for (vals) |val| { @@ -7405,9 +7435,9 @@ fn gepConstAssumeCapacity( pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { if (ctx.builder.constant_items.items(.tag)[rhs_index] != tag) return false; const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index]; - const rhs_extra = ctx.builder.constantExtraDataTrail(Constant.GetElementPtr, rhs_data); - const rhs_indices: []const Constant = @ptrCast(ctx.builder.constant_extra - .items[rhs_extra.end..][0..rhs_extra.data.info.indices_len]); + var rhs_extra = ctx.builder.constantExtraDataTrail(Constant.GetElementPtr, rhs_data); + const rhs_indices = + rhs_extra.trail.next(rhs_extra.data.info.indices_len, Constant, ctx.builder); return lhs_key.type == rhs_extra.data.type and lhs_key.base == rhs_extra.data.base and lhs_key.inrange == rhs_extra.data.info.inrange and std.mem.eql(Constant, lhs_key.indices, rhs_indices); @@ -7767,10 +7797,9 @@ fn getOrPutConstantAggregateAssumeCapacity( pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { if (lhs_key.tag != ctx.builder.constant_items.items(.tag)[rhs_index]) return false; const rhs_data = ctx.builder.constant_items.items(.data)[rhs_index]; - const rhs_extra = ctx.builder.constantExtraDataTrail(Constant.Aggregate, rhs_data); + var rhs_extra = ctx.builder.constantExtraDataTrail(Constant.Aggregate, rhs_data); if (lhs_key.type != rhs_extra.data.type) return false; - const rhs_vals: []const Constant = - @ptrCast(ctx.builder.constant_extra.items[rhs_extra.end..][0..lhs_key.vals.len]); + const rhs_vals = rhs_extra.trail.next(@intCast(lhs_key.vals.len), Constant, ctx.builder); return std.mem.eql(Constant, lhs_key.vals, rhs_vals); } }; @@ -7804,11 +7833,32 @@ fn addConstantExtraAssumeCapacity(self: *Builder, extra: anytype) Constant.Item. return result; } +const ConstantExtraDataTrail = struct { + index: Constant.Item.ExtraIndex, + + fn nextMut(self: *ConstantExtraDataTrail, len: u32, comptime Item: type, builder: *Builder) []Item { + const items: []Item = @ptrCast(builder.constant_extra.items[self.index..][0..len]); + self.index += @intCast(len); + return items; + } + + fn next( + self: *ConstantExtraDataTrail, + len: u32, + comptime Item: type, + builder: *const Builder, + ) []const Item { + const items: []const Item = @ptrCast(builder.constant_extra.items[self.index..][0..len]); + self.index += @intCast(len); + return items; + } +}; + fn constantExtraDataTrail( self: *const Builder, comptime T: type, index: Constant.Item.ExtraIndex, -) struct { data: T, end: Constant.Item.ExtraIndex } { +) struct { data: T, trail: ConstantExtraDataTrail } { var result: T = undefined; const fields = @typeInfo(T).Struct.fields; inline for (fields, self.constant_extra.items[index..][0..fields.len]) |field, value| @@ -7818,7 +7868,10 @@ fn constantExtraDataTrail( Constant.GetElementPtr.Info => @bitCast(value), else => @compileError("bad field type: " ++ @typeName(field.type)), }; - return .{ .data = result, .end = index + @as(Constant.Item.ExtraIndex, @intCast(fields.len)) }; + return .{ + .data = result, + .trail = .{ .index = index + @as(Constant.Item.ExtraIndex, @intCast(fields.len)) }, + }; } fn constantExtraData(self: *const Builder, comptime T: type, index: Constant.Item.ExtraIndex) T {