diff options
| author | antlilja <liljaanton2001@gmail.com> | 2024-02-19 23:02:40 +0100 |
|---|---|---|
| committer | antlilja <liljaanton2001@gmail.com> | 2024-02-21 16:24:59 +0100 |
| commit | a456631e2940ba53dc0e450bc4748cad9071f019 (patch) | |
| tree | 09730248bb03b9573c023bac996e6589709ea109 /src/codegen | |
| parent | b4369dfbda9eae40287972e82febda6bea72f572 (diff) | |
| download | zig-a456631e2940ba53dc0e450bc4748cad9071f019.tar.gz zig-a456631e2940ba53dc0e450bc4748cad9071f019.zip | |
LLVM Builder: Add debug/metadata system
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/llvm/Builder.zig | 1459 |
1 files changed, 1453 insertions, 6 deletions
diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index 8549eb64b0..51841e4141 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -52,6 +52,17 @@ constant_items: std.MultiArrayList(Constant.Item), constant_extra: std.ArrayListUnmanaged(u32), constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb), +metadata_map: std.AutoArrayHashMapUnmanaged(void, void), +metadata_items: std.MultiArrayList(Metadata.Item), +metadata_extra: std.ArrayListUnmanaged(u32), +metadata_strings: std.AutoArrayHashMapUnmanaged(String, void), +metadata_limbs: std.ArrayListUnmanaged(std.math.big.Limb), +metadata_forward_references: std.ArrayListUnmanaged(Metadata), +metadata_named: std.AutoArrayHashMapUnmanaged(String, struct { + len: u32, + index: Metadata.Item.ExtraIndex, +}), + pub const expected_args_len = 16; pub const expected_attrs_len = 16; pub const expected_fields_len = 32; @@ -6403,6 +6414,7 @@ pub const WipFunction = struct { @intFromEnum(instruction) ].toValue(), .constant => |constant| constant.toValue(), + .metadata => |metadata| metadata.toValue(), }; } } = .{ .items = try gpa.alloc(Instruction.Index, self.instructions.len) }; @@ -7400,10 +7412,10 @@ pub const Constant = enum(u32) { false, true, none, - no_init = 1 << 31, + no_init = (1 << 30) - 1, _, - const first_global: Constant = @enumFromInt(1 << 30); + const first_global: Constant = @enumFromInt(1 << 29); pub const Tag = enum(u7) { positive_integer, @@ -8189,22 +8201,27 @@ pub const Value = enum(u32) { true = first_constant + @intFromEnum(Constant.true), _, - const first_constant = 1 << 31; + const first_constant = 1 << 30; + const first_metadata = 1 << 31; pub fn unwrap(self: Value) union(enum) { instruction: Function.Instruction.Index, constant: Constant, + metadata: Metadata, } { return if (@intFromEnum(self) < first_constant) .{ .instruction = @enumFromInt(@intFromEnum(self)) } + else if (@intFromEnum(self) < first_metadata) + .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) } else - .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) }; + .{ .metadata = @enumFromInt(@intFromEnum(self) - first_metadata) }; } pub fn typeOfWip(self: Value, wip: *const WipFunction) Type { return switch (self.unwrap()) { .instruction => |instruction| instruction.typeOfWip(wip), .constant => |constant| constant.typeOf(wip.builder), + .metadata => Type.metadata, }; } @@ -8212,12 +8229,13 @@ pub const Value = enum(u32) { return switch (self.unwrap()) { .instruction => |instruction| instruction.typeOf(function, builder), .constant => |constant| constant.typeOf(builder), + .metadata => Type.metadata, }; } pub fn toConst(self: Value) ?Constant { return switch (self.unwrap()) { - .instruction => null, + .instruction, .metadata => null, .constant => |constant| constant, }; } @@ -8243,6 +8261,7 @@ pub const Value = enum(u32) { .constant = constant, .builder = data.builder, }, fmt_str, fmt_opts, writer), + .metadata => unreachable, } } pub fn fmt(self: Value, function: Function.Index, builder: *Builder) std.fmt.Formatter(format) { @@ -8253,11 +8272,239 @@ pub const Value = enum(u32) { return switch (self.unwrap()) { .instruction => |instruction| instruction.toLlvm(wip), .constant => |constant| constant.toLlvm(wip.builder), + .metadata => unreachable, }; } }; -pub const Metadata = enum(u32) { _ }; +pub const MetadataString = enum(u32) { + _, +}; + +pub const Metadata = enum(u32) { + none = 0, + _, + + const first_forward_reference = 1 << 29; + const first_local_metadata = 1 << 30; + + pub const Tag = enum(u6) { + none, + file, + compile_unit, + @"compile_unit optimized", + subprogram, + @"subprogram optimized", + @"subprogram local", + @"subprogram definition", + @"subprogram optimized local", + @"subprogram optimized definition", + @"subprogram optimized local definition", + @"subprogram local definition", + lexical_block, + location, + basic_bool_type, + basic_unsigned_type, + basic_signed_type, + basic_float_type, + composite_struct_type, + composite_union_type, + composite_enumeration_type, + composite_array_type, + derived_pointer_type, + derived_member_type, + subroutine_type, + enumerator_unsigned, + enumerator_signed_positive, + enumerator_signed_negative, + subrange, + tuple, + module_flag, + expression, + local_var, + parameter, + global_var, + @"global_var local", + global_var_expression, + constant, + }; + + pub fn unwrap(self: Metadata, builder: *const Builder) Metadata { + var metadata = self; + var count: usize = 0; + while (@intFromEnum(metadata) >= Metadata.first_forward_reference and + @intFromEnum(metadata) < Metadata.first_local_metadata) + { + const index = @intFromEnum(metadata) - Metadata.first_forward_reference; + metadata = builder.metadata_forward_references.items[index]; + std.debug.assert(metadata != .none); + count += 1; + } + return metadata; + } + + pub const Item = struct { + tag: Tag, + data: ExtraIndex, + + const ExtraIndex = u32; + }; + + pub const File = struct { + path: MetadataString, + name: MetadataString, + }; + + pub const CompileUnit = struct { + pub const Flags = struct { + optimized: bool, + }; + + file: Metadata, + producer: MetadataString, + enums: Metadata, + globals: Metadata, + }; + + pub const Subprogram = struct { + pub const Flags = struct { + optimized: bool, + local: bool, + definition: bool, + debug_info_flags: u32, + }; + + file: Metadata, + name: MetadataString, + linkage_name: MetadataString, + line: u32, + scope_line: u32, + ty: Metadata, + debug_info_flags: u32, + compile_unit: Metadata, + }; + + pub const LexicalBlock = struct { + file: Metadata, + scope: Metadata, + line: u32, + column: u32, + }; + + pub const Location = struct { + scope: Metadata, + line: u32, + column: u32, + inlined_at: Metadata, + }; + + pub const BasicType = struct { + name: MetadataString, + size_in_bits_lo: u32, + size_in_bits_hi: u32, + }; + + pub const CompositeType = struct { + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits_lo: u32, + size_in_bits_hi: u32, + align_in_bits_lo: u32, + align_in_bits_hi: u32, + fields_tuple: Metadata, + }; + + pub const DerivedType = struct { + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits_lo: u32, + size_in_bits_hi: u32, + align_in_bits_lo: u32, + align_in_bits_hi: u32, + offset_in_bits_lo: u32, + offset_in_bits_hi: u32, + }; + + pub const SubroutineType = struct { + types_tuple: Metadata, + }; + + pub const Enumerator = struct { + name: MetadataString, + bit_width: u32, + limbs_index: u32, + limbs_len: u32, + }; + + pub const Subrange = struct { + lower_bound: Metadata, + count: Metadata, + }; + + pub const Expression = struct { + elements_len: u32, + + // elements: [elements_len]u32 + }; + + pub const Tuple = struct { + elements_len: u32, + + // elements: [elements_len]Metadata + }; + + pub const ModuleFlag = struct { + behaviour: Metadata, + name: MetadataString, + constant: Metadata, + }; + + pub const LocalVar = struct { + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + ty: Metadata, + }; + + pub const Parameter = struct { + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + ty: Metadata, + arg_no: u32, + }; + + pub const GlobalVar = struct { + pub const Flags = struct { + local: bool, + }; + + name: MetadataString, + linkage_name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + ty: Metadata, + variable: Variable.Index, + }; + + pub const GlobalVarExpression = struct { + variable: Metadata, + expression: Metadata, + }; + + pub fn toValue(self: Metadata) Value { + return @enumFromInt(Value.first_metadata + @intFromEnum(self)); + } +}; pub const InitError = error{ InvalidLlvmTriple, @@ -8306,6 +8553,14 @@ pub fn init(options: Options) InitError!Builder { .constant_items = .{}, .constant_extra = .{}, .constant_limbs = .{}, + + .metadata_map = .{}, + .metadata_items = .{}, + .metadata_extra = .{}, + .metadata_strings = .{}, + .metadata_limbs = .{}, + .metadata_forward_references = .{}, + .metadata_named = .{}, }; if (self.useLibLlvm()) self.llvm = .{ .context = llvm.Context.create(), @@ -8395,6 +8650,7 @@ pub fn init(options: Options) InitError!Builder { assert(try self.intConst(.i1, 0) == .false); assert(try self.intConst(.i1, 1) == .true); assert(try self.noneConst(.token) == .none); + assert(try self.debugNone() == .none); return self; } @@ -8445,6 +8701,14 @@ pub fn deinit(self: *Builder) void { self.constant_extra.deinit(self.gpa); self.constant_limbs.deinit(self.gpa); + self.metadata_map.deinit(self.gpa); + self.metadata_items.deinit(self.gpa); + self.metadata_extra.deinit(self.gpa); + self.metadata_strings.deinit(self.gpa); + self.metadata_limbs.deinit(self.gpa); + self.metadata_forward_references.deinit(self.gpa); + self.metadata_named.deinit(self.gpa); + self.* = undefined; } @@ -12042,6 +12306,1188 @@ fn constantExtraData(self: *const Builder, comptime T: type, index: Constant.Ite return self.constantExtraDataTrail(T, index).data; } +fn ensureUnusedMetadataCapacity( + self: *Builder, + count: usize, + comptime Extra: type, + trail_len: usize, +) Allocator.Error!void { + try self.metadata_map.ensureUnusedCapacity(self.gpa, count); + try self.metadata_items.ensureUnusedCapacity(self.gpa, count); + try self.metadata_extra.ensureUnusedCapacity( + self.gpa, + count * (@typeInfo(Extra).Struct.fields.len + trail_len), + ); +} + +fn addMetadataExtraAssumeCapacity(self: *Builder, extra: anytype) Metadata.Item.ExtraIndex { + const result: Metadata.Item.ExtraIndex = @intCast(self.metadata_extra.items.len); + inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| { + const value = @field(extra, field.name); + self.metadata_extra.appendAssumeCapacity(switch (field.type) { + u32 => value, + MetadataString, Metadata, Variable.Index, Value => @intFromEnum(value), + else => @compileError("bad field type: " ++ @typeName(field.type)), + }); + } + return result; +} + +const MetadataExtraDataTrail = struct { + index: Metadata.Item.ExtraIndex, + + fn nextMut(self: *MetadataExtraDataTrail, len: u32, comptime Item: type, builder: *Builder) []Item { + const items: []Item = @ptrCast(builder.metadata_extra.items[self.index..][0..len]); + self.index += @intCast(len); + return items; + } + + fn next( + self: *MetadataExtraDataTrail, + len: u32, + comptime Item: type, + builder: *const Builder, + ) []const Item { + const items: []const Item = @ptrCast(builder.metadata_extra.items[self.index..][0..len]); + self.index += @intCast(len); + return items; + } +}; + +fn metadataExtraDataTrail( + self: *const Builder, + comptime T: type, + index: Metadata.Item.ExtraIndex, +) struct { data: T, trail: MetadataExtraDataTrail } { + var result: T = undefined; + const fields = @typeInfo(T).Struct.fields; + inline for (fields, self.metadata_extra.items[index..][0..fields.len]) |field, value| + @field(result, field.name) = switch (field.type) { + u32 => value, + MetadataString, Metadata, Variable.Index, Value => @enumFromInt(value), + else => @compileError("bad field type: " ++ @typeName(field.type)), + }; + return .{ + .data = result, + .trail = .{ .index = index + @as(Metadata.Item.ExtraIndex, @intCast(fields.len)) }, + }; +} + +fn metadataExtraData(self: *const Builder, comptime T: type, index: Metadata.Item.ExtraIndex) T { + return self.metadataExtraDataTrail(T, index).data; +} + +fn metadataString(self: *Builder, str: String) Allocator.Error!MetadataString { + const gop = try self.metadata_strings.getOrPut(self.gpa, str); + if (!gop.found_existing) gop.key_ptr.* = str; + + return @enumFromInt(gop.index); +} + +pub fn debugNamed(self: *Builder, name: String, operands: []const Metadata) Allocator.Error!void { + try self.metadata_extra.ensureUnusedCapacity( + self.gpa, + operands.len * @sizeOf(Metadata), + ); + try self.metadata_named.ensureUnusedCapacity(self.gpa, 1); + self.debugNamedAssumeCapacity(name, operands); +} + +fn debugNone(self: *Builder) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, NoExtra, 0); + return self.debugNoneAssumeCapacity(); +} + +pub fn debugFile(self: *Builder, path: String, name: String) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.File, 0); + const metadata_path = try self.metadataString(path); + const metadata_name = try self.metadataString(name); + return self.debugFileAssumeCapacity(metadata_path, metadata_name); +} + +pub fn debugCompileUnit( + self: *Builder, + file: Metadata, + producer: String, + enums: Metadata, + globals: Metadata, + flags: Metadata.CompileUnit.Flags, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.CompileUnit, 0); + const metadata_producer = try self.metadataString(producer); + return self.debugCompileUnitAssumeCapacity(file, metadata_producer, enums, globals, flags); +} + +pub fn debugSubprogram( + self: *Builder, + file: Metadata, + name: String, + linkage_name: String, + line: u32, + scope_line: u32, + ty: Metadata, + flags: Metadata.Subprogram.Flags, + compile_unit: Metadata, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.Subprogram, 0); + const metadata_name = try self.metadataString(name); + const metadata_linkage_name = try self.metadataString(linkage_name); + return self.debugSubprogramAssumeCapacity( + file, + metadata_name, + metadata_linkage_name, + line, + scope_line, + ty, + flags, + compile_unit, + ); +} + +pub fn debugLexicalBlock(self: *Builder, file: Metadata, scope: Metadata, line: u32, column: u32) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.LexicalBlock, 0); + return self.debugLexicalBlockAssumeCapacity(file, scope, line, column); +} + +pub fn debugLocation(self: *Builder, scope: Metadata, line: u32, column: u32, inlined_at: Metadata) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.Location, 0); + return self.debugLocationAssumeCapacity(scope, line, column, inlined_at); +} + +pub fn debugBoolType(self: *Builder, name: String, size_in_bits: u64) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0); + const metadata_name = try self.metadataString(name); + return self.debugBoolTypeAssumeCapacity(metadata_name, size_in_bits); +} + +pub fn debugUnsignedType(self: *Builder, name: String, size_in_bits: u64) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0); + const metadata_name = try self.metadataString(name); + return self.debugUnsignedTypeAssumeCapacity(metadata_name, size_in_bits); +} + +pub fn debugSignedType(self: *Builder, name: String, size_in_bits: u64) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0); + const metadata_name = try self.metadataString(name); + return self.debugSignedTypeAssumeCapacity(metadata_name, size_in_bits); +} + +pub fn debugFloatType(self: *Builder, name: String, size_in_bits: u64) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0); + const metadata_name = try self.metadataString(name); + return self.debugFloatTypeAssumeCapacity(metadata_name, size_in_bits); +} + +pub fn debugForwardReference(self: *Builder) Allocator.Error!Metadata { + try self.metadata_forward_references.ensureUnusedCapacity(self.gpa, 1); + return self.debugForwardReferenceAssumeCapacity(); +} + +pub fn debugStructType( + self: *Builder, + name: String, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + fields_tuple: Metadata, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); + const metadata_name = try self.metadataString(name); + return self.debugStructTypeAssumeCapacity( + metadata_name, + file, + scope, + line, + underlying_type, + size_in_bits, + align_in_bits, + fields_tuple, + ); +} + +pub fn debugUnionType( + self: *Builder, + name: String, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + fields_tuple: Metadata, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); + const metadata_name = try self.metadataString(name); + return self.debugUnionTypeAssumeCapacity( + metadata_name, + file, + scope, + line, + underlying_type, + size_in_bits, + align_in_bits, + fields_tuple, + ); +} + +pub fn debugEnumerationType( + self: *Builder, + name: String, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + fields_tuple: Metadata, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); + const metadata_name = try self.metadataString(name); + return self.debugEnumerationTypeAssumeCapacity( + metadata_name, + file, + scope, + line, + underlying_type, + size_in_bits, + align_in_bits, + fields_tuple, + ); +} + +pub fn debugArrayType( + self: *Builder, + name: String, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + fields_tuple: Metadata, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); + const metadata_name = try self.metadataString(name); + return self.debugArrayTypeAssumeCapacity( + metadata_name, + file, + scope, + line, + underlying_type, + size_in_bits, + align_in_bits, + fields_tuple, + ); +} + +pub fn debugPointerType( + self: *Builder, + name: String, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + offset_in_bits: u64, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0); + const metadata_name = try self.metadataString(name); + return self.debugPointerTypeAssumeCapacity( + metadata_name, + file, + scope, + line, + underlying_type, + size_in_bits, + align_in_bits, + offset_in_bits, + ); +} + +pub fn debugMemberType( + self: *Builder, + name: String, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + offset_in_bits: u64, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0); + const metadata_name = try self.metadataString(name); + return self.debugMemberTypeAssumeCapacity( + metadata_name, + file, + scope, + line, + underlying_type, + size_in_bits, + align_in_bits, + offset_in_bits, + ); +} + +pub fn debugSubroutineType( + self: *Builder, + types_tuple: Metadata, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.SubroutineType, 0); + return self.debugSubroutineTypeAssumeCapacity(types_tuple); +} + +pub fn debugEnumerator( + self: *Builder, + name: String, + unsigned: bool, + bit_width: u32, + value: std.math.big.int.Const, +) Allocator.Error!Metadata { + std.debug.assert(!(unsigned and !value.positive)); + try self.ensureUnusedMetadataCapacity(1, Metadata.Enumerator, 0); + try self.metadata_limbs.ensureUnusedCapacity(self.gpa, value.limbs.len); + const metadata_name = try self.metadataString(name); + return self.debugEnumeratorAssumeCapacity(metadata_name, unsigned, bit_width, value); +} + +pub fn debugSubrange( + self: *Builder, + lower_bound: Metadata, + count: Metadata, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.Subrange, 0); + return self.debugSubrangeAssumeCapacity(lower_bound, count); +} + +pub fn debugExpression( + self: *Builder, + elements: []const u32, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.Expression, elements.len * @sizeOf(u32)); + return self.debugExpressionAssumeCapacity(elements); +} + +pub fn debugTuple( + self: *Builder, + elements: []const Metadata, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.Tuple, elements.len * @sizeOf(Metadata)); + return self.debugTupleAssumeCapacity(elements); +} + +pub fn debugModuleFlag( + self: *Builder, + behaviour: Metadata, + name: String, + constant: Metadata, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.ModuleFlag, 0); + const metadata_name = try self.metadataString(name); + return self.debugModuleFlagAssumeCapacity(behaviour, metadata_name, constant); +} + +pub fn debugLocalVar( + self: *Builder, + name: String, + file: Metadata, + scope: Metadata, + line: u32, + ty: Metadata, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.LocalVar, 0); + const metadata_name = try self.metadataString(name); + return self.debugLocalVarAssumeCapacity(metadata_name, file, scope, line, ty); +} + +pub fn debugParameter( + self: *Builder, + name: String, + file: Metadata, + scope: Metadata, + line: u32, + ty: Metadata, + arg_no: u32, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.Parameter, 0); + const metadata_name = try self.metadataString(name); + return self.debugParameterAssumeCapacity(metadata_name, file, scope, line, ty, arg_no); +} + +pub fn debugGlobalVar( + self: *Builder, + name: String, + linkage_name: String, + file: Metadata, + scope: Metadata, + line: u32, + ty: Metadata, + variable: Variable.Index, + flags: Metadata.GlobalVar.Flags, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.GlobalVar, 0); + const metadata_name = try self.metadataString(name); + const metadata_linkage_name = try self.metadataString(linkage_name); + return self.debugGlobalVarAssumeCapacity( + metadata_name, + metadata_linkage_name, + file, + scope, + line, + ty, + variable, + flags, + ); +} + +pub fn debugGlobalVarExpression( + self: *Builder, + variable: Metadata, + expression: Metadata, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.GlobalVarExpression, 0); + return self.debugGlobalVarExpressionAssumeCapacity(variable, expression); +} + +pub fn debugConstant(self: *Builder, value: Constant) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, NoExtra, 0); + return self.debugConstantAssumeCapacity(value); +} + +pub fn debugForwardReferenceSetType(self: *Builder, fwd_ref: Metadata, ty: Metadata) void { + std.debug.assert( + @intFromEnum(fwd_ref) >= Metadata.first_forward_reference and + @intFromEnum(fwd_ref) <= Metadata.first_local_metadata, + ); + const index = @intFromEnum(fwd_ref) - Metadata.first_forward_reference; + self.metadata_forward_references.items[index] = ty; +} + +fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytype) Metadata { + const Key = struct { + tag: Metadata.Tag, + value: @TypeOf(value), + }; + const Adapter = struct { + builder: *const Builder, + pub fn hash(_: @This(), key: Key) u32 { + var hasher = std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(key.tag))); + inline for (std.meta.fields(@TypeOf(value))) |field| { + hasher.update(std.mem.asBytes(&@field(key.value, field.name))); + } + return @truncate(hasher.final()); + } + + pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { + if (lhs_key.tag != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; + const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index]; + const rhs_extra = ctx.builder.metadataExtraData(@TypeOf(value), rhs_data); + inline for (std.meta.fields(@TypeOf(value))) |field| { + const lhs = @field(lhs_key.value, field.name); + const rhs = @field(rhs_extra, field.name); + if (lhs != rhs) return false; + } + return true; + } + }; + + const gop = self.metadata_map.getOrPutAssumeCapacityAdapted( + Key{ .tag = tag, .value = value }, + Adapter{ .builder = self }, + ); + + if (!gop.found_existing) { + gop.key_ptr.* = {}; + gop.value_ptr.* = {}; + self.metadata_items.appendAssumeCapacity(.{ + .tag = tag, + .data = self.addMetadataExtraAssumeCapacity(value), + }); + } + return @enumFromInt(gop.index); +} + +fn debugNamedAssumeCapacity(self: *Builder, name: String, operands: []const Metadata) void { + const extra_index: u32 = @intCast(self.metadata_extra.items.len); + self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(operands)); + + const gop = self.metadata_named.getOrPutAssumeCapacity(name); + gop.value_ptr.* = .{ + .index = extra_index, + .len = @intCast(operands.len), + }; +} + +pub fn debugNoneAssumeCapacity(self: *Builder) Metadata { + return self.metadataSimpleAssumeCapacity(.none, .{}); +} + +fn debugFileAssumeCapacity(self: *Builder, path: MetadataString, name: MetadataString) Metadata { + return self.metadataSimpleAssumeCapacity(.file, Metadata.File{ + .path = path, + .name = name, + }); +} + +pub fn debugCompileUnitAssumeCapacity( + self: *Builder, + file: Metadata, + producer: MetadataString, + enums: Metadata, + globals: Metadata, + flags: Metadata.CompileUnit.Flags, +) Metadata { + return self.metadataSimpleAssumeCapacity( + if (flags.optimized) .@"compile_unit optimized" else .compile_unit, + Metadata.CompileUnit{ + .file = file, + .producer = producer, + .enums = enums, + .globals = globals, + }, + ); +} + +fn debugSubprogramAssumeCapacity( + self: *Builder, + file: Metadata, + name: MetadataString, + linkage_name: MetadataString, + line: u32, + scope_line: u32, + ty: Metadata, + flags: Metadata.Subprogram.Flags, + compile_unit: Metadata, +) Metadata { + const tag: Metadata.Tag = blk: { + var int: u3 = 0; + if (flags.optimized) int |= 0b1; + if (flags.local) int |= 0b10; + if (flags.definition) int |= 0b100; + break :blk switch (int) { + 0 => .subprogram, + 0b1 => .@"subprogram optimized", + 0b10 => .@"subprogram local", + 0b100 => .@"subprogram definition", + 0b011 => .@"subprogram optimized local", + 0b111 => .@"subprogram optimized local definition", + 0b101 => .@"subprogram optimized definition", + 0b110 => .@"subprogram local definition", + }; + }; + return self.metadataSimpleAssumeCapacity(tag, Metadata.Subprogram{ + .file = file, + .name = name, + .linkage_name = linkage_name, + .line = line, + .scope_line = scope_line, + .ty = ty, + .debug_info_flags = flags.debug_info_flags, + .compile_unit = compile_unit, + }); +} + +fn debugLexicalBlockAssumeCapacity(self: *Builder, file: Metadata, scope: Metadata, line: u32, column: u32) Metadata { + return self.metadataSimpleAssumeCapacity(.lexical_block, Metadata.LexicalBlock{ + .file = file, + .scope = scope, + .line = line, + .column = column, + }); +} + +fn debugLocationAssumeCapacity(self: *Builder, scope: Metadata, line: u32, column: u32, inlined_at: Metadata) Metadata { + return self.metadataSimpleAssumeCapacity(.location, Metadata.Location{ + .scope = scope, + .line = line, + .column = column, + .inlined_at = inlined_at, + }); +} + +fn debugBoolTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata { + return self.metadataSimpleAssumeCapacity(.basic_bool_type, Metadata.BasicType{ + .name = name, + .size_in_bits_lo = @truncate(size_in_bits), + .size_in_bits_hi = @truncate(size_in_bits >> 32), + }); +} + +fn debugUnsignedTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata { + return self.metadataSimpleAssumeCapacity(.basic_unsigned_type, Metadata.BasicType{ + .name = name, + .size_in_bits_lo = @truncate(size_in_bits), + .size_in_bits_hi = @truncate(size_in_bits >> 32), + }); +} + +fn debugSignedTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata { + return self.metadataSimpleAssumeCapacity(.basic_signed_type, Metadata.BasicType{ + .name = name, + .size_in_bits_lo = @truncate(size_in_bits), + .size_in_bits_hi = @truncate(size_in_bits >> 32), + }); +} + +fn debugFloatTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata { + return self.metadataSimpleAssumeCapacity(.basic_float_type, Metadata.BasicType{ + .name = name, + .size_in_bits_lo = @truncate(size_in_bits), + .size_in_bits_hi = @truncate(size_in_bits >> 32), + }); +} + +fn debugForwardReferenceAssumeCapacity(self: *Builder) Metadata { + const index = Metadata.first_forward_reference + self.metadata_forward_references.items.len; + self.metadata_forward_references.appendAssumeCapacity(.none); + return @enumFromInt(index); +} + +fn debugStructTypeAssumeCapacity( + self: *Builder, + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + fields_tuple: Metadata, +) Metadata { + return self.debugCompositeTypeAssumeCapacity( + .composite_struct_type, + name, + file, + scope, + line, + underlying_type, + size_in_bits, + align_in_bits, + fields_tuple, + ); +} + +fn debugUnionTypeAssumeCapacity( + self: *Builder, + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + fields_tuple: Metadata, +) Metadata { + return self.debugCompositeTypeAssumeCapacity( + .composite_union_type, + name, + file, + scope, + line, + underlying_type, + size_in_bits, + align_in_bits, + fields_tuple, + ); +} + +fn debugEnumerationTypeAssumeCapacity( + self: *Builder, + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + fields_tuple: Metadata, +) Metadata { + return self.debugCompositeTypeAssumeCapacity( + .composite_enumeration_type, + name, + file, + scope, + line, + underlying_type, + size_in_bits, + align_in_bits, + fields_tuple, + ); +} + +fn debugArrayTypeAssumeCapacity( + self: *Builder, + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + fields_tuple: Metadata, +) Metadata { + return self.debugCompositeTypeAssumeCapacity( + .composite_array_type, + name, + file, + scope, + line, + underlying_type, + size_in_bits, + align_in_bits, + fields_tuple, + ); +} + +fn debugCompositeTypeAssumeCapacity( + self: *Builder, + tag: Metadata.Tag, + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + fields_tuple: Metadata, +) Metadata { + const Key = struct { + tag: Metadata.Tag, + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + fields_tuple: Metadata, + }; + const Adapter = struct { + builder: *const Builder, + pub fn hash(_: @This(), key: Key) u32 { + var hasher = std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(key.tag))); + hasher.update(std.mem.asBytes(&key.name)); + hasher.update(std.mem.asBytes(&key.file)); + hasher.update(std.mem.asBytes(&key.scope)); + hasher.update(std.mem.asBytes(&key.line)); + hasher.update(std.mem.asBytes(&key.underlying_type)); + hasher.update(std.mem.asBytes(&key.size_in_bits)); + hasher.update(std.mem.asBytes(&key.align_in_bits)); + hasher.update(std.mem.asBytes(&key.fields_tuple)); + return @truncate(hasher.final()); + } + + pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { + if (lhs_key.tag != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; + const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index]; + const rhs_extra = ctx.builder.metadataExtraData(Metadata.CompositeType, rhs_data); + const rhs_size_in_bits = @as(u64, rhs_extra.size_in_bits_lo) | @as(u64, rhs_extra.size_in_bits_hi) << 32; + const rhs_align_in_bits = @as(u64, rhs_extra.align_in_bits_lo) | @as(u64, rhs_extra.align_in_bits_hi) << 32; + return lhs_key.name == rhs_extra.name and + lhs_key.file == rhs_extra.file and + lhs_key.scope == rhs_extra.scope and + lhs_key.line == rhs_extra.line and + lhs_key.underlying_type == rhs_extra.underlying_type and + lhs_key.size_in_bits == rhs_size_in_bits and + lhs_key.align_in_bits == rhs_align_in_bits and + lhs_key.fields_tuple == rhs_extra.fields_tuple; + } + }; + + const gop = self.metadata_map.getOrPutAssumeCapacityAdapted( + Key{ + .tag = tag, + .name = name, + .file = file, + .scope = scope, + .line = line, + .underlying_type = underlying_type, + .size_in_bits = size_in_bits, + .align_in_bits = align_in_bits, + .fields_tuple = fields_tuple, + }, + Adapter{ .builder = self }, + ); + + if (!gop.found_existing) { + gop.key_ptr.* = {}; + gop.value_ptr.* = {}; + self.metadata_items.appendAssumeCapacity(.{ + .tag = tag, + .data = self.addMetadataExtraAssumeCapacity(Metadata.CompositeType{ + .name = name, + .file = file, + .scope = scope, + .line = line, + .underlying_type = underlying_type, + .size_in_bits_lo = @truncate(size_in_bits), + .size_in_bits_hi = @truncate(size_in_bits >> 32), + .align_in_bits_lo = @truncate(align_in_bits), + .align_in_bits_hi = @truncate(align_in_bits >> 32), + .fields_tuple = fields_tuple, + }), + }); + } + return @enumFromInt(gop.index); +} + +fn debugPointerTypeAssumeCapacity( + self: *Builder, + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + offset_in_bits: u64, +) Metadata { + return self.metadataSimpleAssumeCapacity(.derived_pointer_type, Metadata.DerivedType{ + .name = name, + .file = file, + .scope = scope, + .line = line, + .underlying_type = underlying_type, + .size_in_bits_lo = @truncate(size_in_bits), + .size_in_bits_hi = @truncate(size_in_bits >> 32), + .align_in_bits_lo = @truncate(align_in_bits), + .align_in_bits_hi = @truncate(align_in_bits >> 32), + .offset_in_bits_lo = @truncate(offset_in_bits), + .offset_in_bits_hi = @truncate(offset_in_bits >> 32), + }); +} + +fn debugMemberTypeAssumeCapacity( + self: *Builder, + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + size_in_bits: u64, + align_in_bits: u64, + offset_in_bits: u64, +) Metadata { + return self.metadataSimpleAssumeCapacity(.derived_member_type, Metadata.DerivedType{ + .name = name, + .file = file, + .scope = scope, + .line = line, + .underlying_type = underlying_type, + .size_in_bits_lo = @truncate(size_in_bits), + .size_in_bits_hi = @truncate(size_in_bits >> 32), + .align_in_bits_lo = @truncate(align_in_bits), + .align_in_bits_hi = @truncate(align_in_bits >> 32), + .offset_in_bits_lo = @truncate(offset_in_bits), + .offset_in_bits_hi = @truncate(offset_in_bits >> 32), + }); +} + +fn debugSubroutineTypeAssumeCapacity( + self: *Builder, + types_tuple: Metadata, +) Metadata { + return self.metadataSimpleAssumeCapacity(.subroutine_type, Metadata.SubroutineType{ + .types_tuple = types_tuple, + }); +} + +fn debugEnumeratorAssumeCapacity( + self: *Builder, + name: MetadataString, + unsigned: bool, + bit_width: u32, + value: std.math.big.int.Const, +) Metadata { + const Key = struct { + tag: Metadata.Tag, + name: MetadataString, + bit_width: u32, + value: std.math.big.int.Const, + }; + const Adapter = struct { + builder: *const Builder, + pub fn hash(_: @This(), key: Key) u32 { + var hasher = std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(key.tag))); + hasher.update(std.mem.asBytes(&key.name)); + hasher.update(std.mem.asBytes(&key.bit_width)); + hasher.update(std.mem.sliceAsBytes(key.value.limbs)); + return @truncate(hasher.final()); + } + + pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { + if (lhs_key.tag != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; + const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index]; + const rhs_extra = ctx.builder.metadataExtraData(Metadata.Enumerator, rhs_data); + const limbs = ctx.builder.metadata_limbs + .items[rhs_extra.limbs_index..][0..rhs_extra.limbs_len]; + const rhs_value = std.math.big.int.Const{ + .limbs = limbs, + .positive = lhs_key.value.positive, + }; + return lhs_key.name == rhs_extra.name and + lhs_key.bit_width == rhs_extra.bit_width and + lhs_key.value.eql(rhs_value); + } + }; + + const tag: Metadata.Tag = if (unsigned) + .enumerator_unsigned + else if (value.positive) .enumerator_signed_positive else .enumerator_signed_negative; + + std.debug.assert(!(tag == .enumerator_unsigned and !value.positive)); + + const gop = self.metadata_map.getOrPutAssumeCapacityAdapted( + Key{ + .tag = tag, + .name = name, + .bit_width = bit_width, + .value = value, + }, + Adapter{ .builder = self }, + ); + + if (!gop.found_existing) { + gop.key_ptr.* = {}; + gop.value_ptr.* = {}; + self.metadata_items.appendAssumeCapacity(.{ + .tag = tag, + .data = self.addMetadataExtraAssumeCapacity(Metadata.Enumerator{ + .name = name, + .bit_width = bit_width, + .limbs_index = @intCast(self.metadata_limbs.items.len), + .limbs_len = @intCast(value.limbs.len), + }), + }); + self.metadata_limbs.appendSliceAssumeCapacity(value.limbs); + } + return @enumFromInt(gop.index); +} + +fn debugSubrangeAssumeCapacity( + self: *Builder, + lower_bound: Metadata, + count: Metadata, +) Metadata { + return self.metadataSimpleAssumeCapacity(.subrange, Metadata.Subrange{ + .lower_bound = lower_bound, + .count = count, + }); +} + +fn debugExpressionAssumeCapacity( + self: *Builder, + elements: []const u32, +) Metadata { + const Key = struct { + elements: []const u32, + }; + const Adapter = struct { + builder: *const Builder, + pub fn hash(_: @This(), key: Key) u32 { + var hasher = comptime std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(Metadata.Tag.expression))); + hasher.update(std.mem.sliceAsBytes(key.elements)); + return @truncate(hasher.final()); + } + + pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { + if (Metadata.Tag.expression != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; + const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index]; + var rhs_extra = ctx.builder.metadataExtraDataTrail(Metadata.Expression, rhs_data); + return std.mem.eql( + u32, + lhs_key.elements, + rhs_extra.trail.next(rhs_extra.data.elements_len, u32, ctx.builder), + ); + } + }; + + const gop = self.metadata_map.getOrPutAssumeCapacityAdapted( + Key{ .elements = elements }, + Adapter{ .builder = self }, + ); + + if (!gop.found_existing) { + gop.key_ptr.* = {}; + gop.value_ptr.* = {}; + self.metadata_items.appendAssumeCapacity(.{ + .tag = .expression, + .data = self.addMetadataExtraAssumeCapacity(Metadata.Expression{ + .elements_len = @intCast(elements.len), + }), + }); + self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(elements)); + } + return @enumFromInt(gop.index); +} + +fn debugTupleAssumeCapacity( + self: *Builder, + elements: []const Metadata, +) Metadata { + const Key = struct { + elements: []const Metadata, + }; + const Adapter = struct { + builder: *const Builder, + pub fn hash(_: @This(), key: Key) u32 { + var hasher = comptime std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(Metadata.Tag.tuple))); + hasher.update(std.mem.sliceAsBytes(key.elements)); + return @truncate(hasher.final()); + } + + pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool { + if (Metadata.Tag.tuple != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; + const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index]; + var rhs_extra = ctx.builder.metadataExtraDataTrail(Metadata.Tuple, rhs_data); + return std.mem.eql( + Metadata, + lhs_key.elements, + rhs_extra.trail.next(rhs_extra.data.elements_len, Metadata, ctx.builder), + ); + } + }; + + const gop = self.metadata_map.getOrPutAssumeCapacityAdapted( + Key{ .elements = elements }, + Adapter{ .builder = self }, + ); + + if (!gop.found_existing) { + gop.key_ptr.* = {}; + gop.value_ptr.* = {}; + self.metadata_items.appendAssumeCapacity(.{ + .tag = .tuple, + .data = self.addMetadataExtraAssumeCapacity(Metadata.Tuple{ + .elements_len = @intCast(elements.len), + }), + }); + self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(elements)); + } + return @enumFromInt(gop.index); +} + +fn debugModuleFlagAssumeCapacity( + self: *Builder, + behaviour: Metadata, + name: MetadataString, + constant: Metadata, +) Metadata { + return self.metadataSimpleAssumeCapacity(.module_flag, Metadata.ModuleFlag{ + .behaviour = behaviour, + .name = name, + .constant = constant, + }); +} + +fn debugLocalVarAssumeCapacity( + self: *Builder, + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + ty: Metadata, +) Allocator.Error!Metadata { + return self.metadataSimpleAssumeCapacity(.local_var, Metadata.LocalVar{ + .name = name, + .file = file, + .scope = scope, + .line = line, + .ty = ty, + }); +} + +fn debugParameterAssumeCapacity( + self: *Builder, + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + ty: Metadata, + arg_no: u32, +) Allocator.Error!Metadata { + return self.metadataSimpleAssumeCapacity(.parameter, Metadata.Parameter{ + .name = name, + .file = file, + .scope = scope, + .line = line, + .ty = ty, + .arg_no = arg_no, + }); +} + +fn debugGlobalVarAssumeCapacity( + self: *Builder, + name: MetadataString, + linkage_name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + ty: Metadata, + variable: Variable.Index, + flags: Metadata.GlobalVar.Flags, +) Allocator.Error!Metadata { + return self.metadataSimpleAssumeCapacity( + if (flags.local) .@"global_var local" else .global_var, + Metadata.GlobalVar{ + .name = name, + .linkage_name = linkage_name, + .file = file, + .scope = scope, + .line = line, + .ty = ty, + .variable = variable, + }, + ); +} + +fn debugGlobalVarExpressionAssumeCapacity( + self: *Builder, + variable: Metadata, + expression: Metadata, +) Metadata { + return self.metadataSimpleAssumeCapacity(.global_var_expression, Metadata.GlobalVarExpression{ + .variable = variable, + .expression = expression, + }); +} + +fn debugConstantAssumeCapacity(self: *Builder, constant: Constant) Metadata { + const Adapter = struct { + builder: *const Builder, + pub fn hash(_: @This(), key: Constant) u32 { + var hasher = comptime std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(Metadata.Tag.constant))); + hasher.update(std.mem.asBytes(&key)); + return @truncate(hasher.final()); + } + + pub fn eql(ctx: @This(), lhs_key: Constant, _: void, rhs_index: usize) bool { + if (Metadata.Tag.constant != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false; + const rhs_data: Constant = @enumFromInt(ctx.builder.metadata_items.items(.data)[rhs_index]); + return rhs_data == lhs_key; + } + }; + + const gop = self.metadata_map.getOrPutAssumeCapacityAdapted( + constant, + Adapter{ .builder = self }, + ); + + if (!gop.found_existing) { + gop.key_ptr.* = {}; + gop.value_ptr.* = {}; + self.metadata_items.appendAssumeCapacity(.{ + .tag = .constant, + .data = @intFromEnum(constant), + }); + } + return @enumFromInt(gop.index); +} + pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]const u32 { const BitcodeWriter = bitcode_writer.BitcodeWriter(&.{ Type, FunctionAttributes }); var bitcode = BitcodeWriter.init(allocator, &.{ @@ -12977,6 +14423,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co return @intCast(switch (value.unwrap()) { .instruction => |instruction| instruction.valueIndex(adapter.func) + adapter.firstInstr(), .constant => |constant| adapter.constant_adapter.getConstantIndex(constant), + .metadata => unreachable, }); } |
