authorgravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2024-02-19 23:02:40+01:00
committergravatar for liljaanton2001@gmail.comantlilja <liljaanton2001@gmail.com> 2024-02-21 16:24:59+01:00
loga456631e2940ba53dc0e450bc4748cad9071f019
tree09730248bb03b9573c023bac996e6589709ea109
parentb4369dfbda9eae40287972e82febda6bea72f572

LLVM Builder: Add debug/metadata system


1 files changed, 1453 insertions(+), 6 deletions(-)

src/codegen/llvm/Builder.zig+1453-6
...@@ -52,6 +52,17 @@ constant_items: std.MultiArrayList(Constant.Item),...@@ -52,6 +52,17 @@ constant_items: std.MultiArrayList(Constant.Item),
52constant_extra: std.ArrayListUnmanaged(u32),52constant_extra: std.ArrayListUnmanaged(u32),
53constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb),53constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb),
5454
55metadata_map: std.AutoArrayHashMapUnmanaged(void, void),
56metadata_items: std.MultiArrayList(Metadata.Item),
57metadata_extra: std.ArrayListUnmanaged(u32),
58metadata_strings: std.AutoArrayHashMapUnmanaged(String, void),
59metadata_limbs: std.ArrayListUnmanaged(std.math.big.Limb),
60metadata_forward_references: std.ArrayListUnmanaged(Metadata),
61metadata_named: std.AutoArrayHashMapUnmanaged(String, struct {
62 len: u32,
63 index: Metadata.Item.ExtraIndex,
64}),
65
55pub const expected_args_len = 16;66pub const expected_args_len = 16;
56pub const expected_attrs_len = 16;67pub const expected_attrs_len = 16;
57pub const expected_fields_len = 32;68pub const expected_fields_len = 32;
...@@ -6403,6 +6414,7 @@ pub const WipFunction = struct {...@@ -6403,6 +6414,7 @@ pub const WipFunction = struct {
6403 @intFromEnum(instruction)6414 @intFromEnum(instruction)
6404 ].toValue(),6415 ].toValue(),
6405 .constant => |constant| constant.toValue(),6416 .constant => |constant| constant.toValue(),
6417 .metadata => |metadata| metadata.toValue(),
6406 };6418 };
6407 }6419 }
6408 } = .{ .items = try gpa.alloc(Instruction.Index, self.instructions.len) };6420 } = .{ .items = try gpa.alloc(Instruction.Index, self.instructions.len) };
...@@ -7400,10 +7412,10 @@ pub const Constant = enum(u32) {...@@ -7400,10 +7412,10 @@ pub const Constant = enum(u32) {
7400 false,7412 false,
7401 true,7413 true,
7402 none,7414 none,
7403 no_init = 1 << 31,7415 no_init = (1 << 30) - 1,
7404 _,7416 _,
74057417
7406 const first_global: Constant = @enumFromInt(1 << 30);7418 const first_global: Constant = @enumFromInt(1 << 29);
74077419
7408 pub const Tag = enum(u7) {7420 pub const Tag = enum(u7) {
7409 positive_integer,7421 positive_integer,
...@@ -8189,22 +8201,27 @@ pub const Value = enum(u32) {...@@ -8189,22 +8201,27 @@ pub const Value = enum(u32) {
8189 true = first_constant + @intFromEnum(Constant.true),8201 true = first_constant + @intFromEnum(Constant.true),
8190 _,8202 _,
81918203
8192 const first_constant = 1 << 31;8204 const first_constant = 1 << 30;
8205 const first_metadata = 1 << 31;
81938206
8194 pub fn unwrap(self: Value) union(enum) {8207 pub fn unwrap(self: Value) union(enum) {
8195 instruction: Function.Instruction.Index,8208 instruction: Function.Instruction.Index,
8196 constant: Constant,8209 constant: Constant,
8210 metadata: Metadata,
8197 } {8211 } {
8198 return if (@intFromEnum(self) < first_constant)8212 return if (@intFromEnum(self) < first_constant)
8199 .{ .instruction = @enumFromInt(@intFromEnum(self)) }8213 .{ .instruction = @enumFromInt(@intFromEnum(self)) }
8214 else if (@intFromEnum(self) < first_metadata)
8215 .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) }
8200 else8216 else
8201 .{ .constant = @enumFromInt(@intFromEnum(self) - first_constant) };8217 .{ .metadata = @enumFromInt(@intFromEnum(self) - first_metadata) };
8202 }8218 }
82038219
8204 pub fn typeOfWip(self: Value, wip: *const WipFunction) Type {8220 pub fn typeOfWip(self: Value, wip: *const WipFunction) Type {
8205 return switch (self.unwrap()) {8221 return switch (self.unwrap()) {
8206 .instruction => |instruction| instruction.typeOfWip(wip),8222 .instruction => |instruction| instruction.typeOfWip(wip),
8207 .constant => |constant| constant.typeOf(wip.builder),8223 .constant => |constant| constant.typeOf(wip.builder),
8224 .metadata => Type.metadata,
8208 };8225 };
8209 }8226 }
82108227
...@@ -8212,12 +8229,13 @@ pub const Value = enum(u32) {...@@ -8212,12 +8229,13 @@ pub const Value = enum(u32) {
8212 return switch (self.unwrap()) {8229 return switch (self.unwrap()) {
8213 .instruction => |instruction| instruction.typeOf(function, builder),8230 .instruction => |instruction| instruction.typeOf(function, builder),
8214 .constant => |constant| constant.typeOf(builder),8231 .constant => |constant| constant.typeOf(builder),
8232 .metadata => Type.metadata,
8215 };8233 };
8216 }8234 }
82178235
8218 pub fn toConst(self: Value) ?Constant {8236 pub fn toConst(self: Value) ?Constant {
8219 return switch (self.unwrap()) {8237 return switch (self.unwrap()) {
8220 .instruction => null,8238 .instruction, .metadata => null,
8221 .constant => |constant| constant,8239 .constant => |constant| constant,
8222 };8240 };
8223 }8241 }
...@@ -8243,6 +8261,7 @@ pub const Value = enum(u32) {...@@ -8243,6 +8261,7 @@ pub const Value = enum(u32) {
8243 .constant = constant,8261 .constant = constant,
8244 .builder = data.builder,8262 .builder = data.builder,
8245 }, fmt_str, fmt_opts, writer),8263 }, fmt_str, fmt_opts, writer),
8264 .metadata => unreachable,
8246 }8265 }
8247 }8266 }
8248 pub fn fmt(self: Value, function: Function.Index, builder: *Builder) std.fmt.Formatter(format) {8267 pub fn fmt(self: Value, function: Function.Index, builder: *Builder) std.fmt.Formatter(format) {
...@@ -8253,11 +8272,239 @@ pub const Value = enum(u32) {...@@ -8253,11 +8272,239 @@ pub const Value = enum(u32) {
8253 return switch (self.unwrap()) {8272 return switch (self.unwrap()) {
8254 .instruction => |instruction| instruction.toLlvm(wip),8273 .instruction => |instruction| instruction.toLlvm(wip),
8255 .constant => |constant| constant.toLlvm(wip.builder),8274 .constant => |constant| constant.toLlvm(wip.builder),
8275 .metadata => unreachable,
8256 };8276 };
8257 }8277 }
8258};8278};
82598279
8260pub const Metadata = enum(u32) { _ };8280pub const MetadataString = enum(u32) {
8281 _,
8282};
8283
8284pub const Metadata = enum(u32) {
8285 none = 0,
8286 _,
8287
8288 const first_forward_reference = 1 << 29;
8289 const first_local_metadata = 1 << 30;
8290
8291 pub const Tag = enum(u6) {
8292 none,
8293 file,
8294 compile_unit,
8295 @"compile_unit optimized",
8296 subprogram,
8297 @"subprogram optimized",
8298 @"subprogram local",
8299 @"subprogram definition",
8300 @"subprogram optimized local",
8301 @"subprogram optimized definition",
8302 @"subprogram optimized local definition",
8303 @"subprogram local definition",
8304 lexical_block,
8305 location,
8306 basic_bool_type,
8307 basic_unsigned_type,
8308 basic_signed_type,
8309 basic_float_type,
8310 composite_struct_type,
8311 composite_union_type,
8312 composite_enumeration_type,
8313 composite_array_type,
8314 derived_pointer_type,
8315 derived_member_type,
8316 subroutine_type,
8317 enumerator_unsigned,
8318 enumerator_signed_positive,
8319 enumerator_signed_negative,
8320 subrange,
8321 tuple,
8322 module_flag,
8323 expression,
8324 local_var,
8325 parameter,
8326 global_var,
8327 @"global_var local",
8328 global_var_expression,
8329 constant,
8330 };
8331
8332 pub fn unwrap(self: Metadata, builder: *const Builder) Metadata {
8333 var metadata = self;
8334 var count: usize = 0;
8335 while (@intFromEnum(metadata) >= Metadata.first_forward_reference and
8336 @intFromEnum(metadata) < Metadata.first_local_metadata)
8337 {
8338 const index = @intFromEnum(metadata) - Metadata.first_forward_reference;
8339 metadata = builder.metadata_forward_references.items[index];
8340 std.debug.assert(metadata != .none);
8341 count += 1;
8342 }
8343 return metadata;
8344 }
8345
8346 pub const Item = struct {
8347 tag: Tag,
8348 data: ExtraIndex,
8349
8350 const ExtraIndex = u32;
8351 };
8352
8353 pub const File = struct {
8354 path: MetadataString,
8355 name: MetadataString,
8356 };
8357
8358 pub const CompileUnit = struct {
8359 pub const Flags = struct {
8360 optimized: bool,
8361 };
8362
8363 file: Metadata,
8364 producer: MetadataString,
8365 enums: Metadata,
8366 globals: Metadata,
8367 };
8368
8369 pub const Subprogram = struct {
8370 pub const Flags = struct {
8371 optimized: bool,
8372 local: bool,
8373 definition: bool,
8374 debug_info_flags: u32,
8375 };
8376
8377 file: Metadata,
8378 name: MetadataString,
8379 linkage_name: MetadataString,
8380 line: u32,
8381 scope_line: u32,
8382 ty: Metadata,
8383 debug_info_flags: u32,
8384 compile_unit: Metadata,
8385 };
8386
8387 pub const LexicalBlock = struct {
8388 file: Metadata,
8389 scope: Metadata,
8390 line: u32,
8391 column: u32,
8392 };
8393
8394 pub const Location = struct {
8395 scope: Metadata,
8396 line: u32,
8397 column: u32,
8398 inlined_at: Metadata,
8399 };
8400
8401 pub const BasicType = struct {
8402 name: MetadataString,
8403 size_in_bits_lo: u32,
8404 size_in_bits_hi: u32,
8405 };
8406
8407 pub const CompositeType = struct {
8408 name: MetadataString,
8409 file: Metadata,
8410 scope: Metadata,
8411 line: u32,
8412 underlying_type: Metadata,
8413 size_in_bits_lo: u32,
8414 size_in_bits_hi: u32,
8415 align_in_bits_lo: u32,
8416 align_in_bits_hi: u32,
8417 fields_tuple: Metadata,
8418 };
8419
8420 pub const DerivedType = struct {
8421 name: MetadataString,
8422 file: Metadata,
8423 scope: Metadata,
8424 line: u32,
8425 underlying_type: Metadata,
8426 size_in_bits_lo: u32,
8427 size_in_bits_hi: u32,
8428 align_in_bits_lo: u32,
8429 align_in_bits_hi: u32,
8430 offset_in_bits_lo: u32,
8431 offset_in_bits_hi: u32,
8432 };
8433
8434 pub const SubroutineType = struct {
8435 types_tuple: Metadata,
8436 };
8437
8438 pub const Enumerator = struct {
8439 name: MetadataString,
8440 bit_width: u32,
8441 limbs_index: u32,
8442 limbs_len: u32,
8443 };
8444
8445 pub const Subrange = struct {
8446 lower_bound: Metadata,
8447 count: Metadata,
8448 };
8449
8450 pub const Expression = struct {
8451 elements_len: u32,
8452
8453 // elements: [elements_len]u32
8454 };
8455
8456 pub const Tuple = struct {
8457 elements_len: u32,
8458
8459 // elements: [elements_len]Metadata
8460 };
8461
8462 pub const ModuleFlag = struct {
8463 behaviour: Metadata,
8464 name: MetadataString,
8465 constant: Metadata,
8466 };
8467
8468 pub const LocalVar = struct {
8469 name: MetadataString,
8470 file: Metadata,
8471 scope: Metadata,
8472 line: u32,
8473 ty: Metadata,
8474 };
8475
8476 pub const Parameter = struct {
8477 name: MetadataString,
8478 file: Metadata,
8479 scope: Metadata,
8480 line: u32,
8481 ty: Metadata,
8482 arg_no: u32,
8483 };
8484
8485 pub const GlobalVar = struct {
8486 pub const Flags = struct {
8487 local: bool,
8488 };
8489
8490 name: MetadataString,
8491 linkage_name: MetadataString,
8492 file: Metadata,
8493 scope: Metadata,
8494 line: u32,
8495 ty: Metadata,
8496 variable: Variable.Index,
8497 };
8498
8499 pub const GlobalVarExpression = struct {
8500 variable: Metadata,
8501 expression: Metadata,
8502 };
8503
8504 pub fn toValue(self: Metadata) Value {
8505 return @enumFromInt(Value.first_metadata + @intFromEnum(self));
8506 }
8507};
82618508
8262pub const InitError = error{8509pub const InitError = error{
8263 InvalidLlvmTriple,8510 InvalidLlvmTriple,
...@@ -8306,6 +8553,14 @@ pub fn init(options: Options) InitError!Builder {...@@ -8306,6 +8553,14 @@ pub fn init(options: Options) InitError!Builder {
8306 .constant_items = .{},8553 .constant_items = .{},
8307 .constant_extra = .{},8554 .constant_extra = .{},
8308 .constant_limbs = .{},8555 .constant_limbs = .{},
8556
8557 .metadata_map = .{},
8558 .metadata_items = .{},
8559 .metadata_extra = .{},
8560 .metadata_strings = .{},
8561 .metadata_limbs = .{},
8562 .metadata_forward_references = .{},
8563 .metadata_named = .{},
8309 };8564 };
8310 if (self.useLibLlvm()) self.llvm = .{8565 if (self.useLibLlvm()) self.llvm = .{
8311 .context = llvm.Context.create(),8566 .context = llvm.Context.create(),
...@@ -8395,6 +8650,7 @@ pub fn init(options: Options) InitError!Builder {...@@ -8395,6 +8650,7 @@ pub fn init(options: Options) InitError!Builder {
8395 assert(try self.intConst(.i1, 0) == .false);8650 assert(try self.intConst(.i1, 0) == .false);
8396 assert(try self.intConst(.i1, 1) == .true);8651 assert(try self.intConst(.i1, 1) == .true);
8397 assert(try self.noneConst(.token) == .none);8652 assert(try self.noneConst(.token) == .none);
8653 assert(try self.debugNone() == .none);
83988654
8399 return self;8655 return self;
8400}8656}
...@@ -8445,6 +8701,14 @@ pub fn deinit(self: *Builder) void {...@@ -8445,6 +8701,14 @@ pub fn deinit(self: *Builder) void {
8445 self.constant_extra.deinit(self.gpa);8701 self.constant_extra.deinit(self.gpa);
8446 self.constant_limbs.deinit(self.gpa);8702 self.constant_limbs.deinit(self.gpa);
84478703
8704 self.metadata_map.deinit(self.gpa);
8705 self.metadata_items.deinit(self.gpa);
8706 self.metadata_extra.deinit(self.gpa);
8707 self.metadata_strings.deinit(self.gpa);
8708 self.metadata_limbs.deinit(self.gpa);
8709 self.metadata_forward_references.deinit(self.gpa);
8710 self.metadata_named.deinit(self.gpa);
8711
8448 self.* = undefined;8712 self.* = undefined;
8449}8713}
84508714
...@@ -12042,6 +12306,1188 @@ fn constantExtraData(self: *const Builder, comptime T: type, index: Constant.Ite...@@ -12042,6 +12306,1188 @@ fn constantExtraData(self: *const Builder, comptime T: type, index: Constant.Ite
12042 return self.constantExtraDataTrail(T, index).data;12306 return self.constantExtraDataTrail(T, index).data;
12043}12307}
1204412308
12309fn ensureUnusedMetadataCapacity(
12310 self: *Builder,
12311 count: usize,
12312 comptime Extra: type,
12313 trail_len: usize,
12314) Allocator.Error!void {
12315 try self.metadata_map.ensureUnusedCapacity(self.gpa, count);
12316 try self.metadata_items.ensureUnusedCapacity(self.gpa, count);
12317 try self.metadata_extra.ensureUnusedCapacity(
12318 self.gpa,
12319 count * (@typeInfo(Extra).Struct.fields.len + trail_len),
12320 );
12321}
12322
12323fn addMetadataExtraAssumeCapacity(self: *Builder, extra: anytype) Metadata.Item.ExtraIndex {
12324 const result: Metadata.Item.ExtraIndex = @intCast(self.metadata_extra.items.len);
12325 inline for (@typeInfo(@TypeOf(extra)).Struct.fields) |field| {
12326 const value = @field(extra, field.name);
12327 self.metadata_extra.appendAssumeCapacity(switch (field.type) {
12328 u32 => value,
12329 MetadataString, Metadata, Variable.Index, Value => @intFromEnum(value),
12330 else => @compileError("bad field type: " ++ @typeName(field.type)),
12331 });
12332 }
12333 return result;
12334}
12335
12336const MetadataExtraDataTrail = struct {
12337 index: Metadata.Item.ExtraIndex,
12338
12339 fn nextMut(self: *MetadataExtraDataTrail, len: u32, comptime Item: type, builder: *Builder) []Item {
12340 const items: []Item = @ptrCast(builder.metadata_extra.items[self.index..][0..len]);
12341 self.index += @intCast(len);
12342 return items;
12343 }
12344
12345 fn next(
12346 self: *MetadataExtraDataTrail,
12347 len: u32,
12348 comptime Item: type,
12349 builder: *const Builder,
12350 ) []const Item {
12351 const items: []const Item = @ptrCast(builder.metadata_extra.items[self.index..][0..len]);
12352 self.index += @intCast(len);
12353 return items;
12354 }
12355};
12356
12357fn metadataExtraDataTrail(
12358 self: *const Builder,
12359 comptime T: type,
12360 index: Metadata.Item.ExtraIndex,
12361) struct { data: T, trail: MetadataExtraDataTrail } {
12362 var result: T = undefined;
12363 const fields = @typeInfo(T).Struct.fields;
12364 inline for (fields, self.metadata_extra.items[index..][0..fields.len]) |field, value|
12365 @field(result, field.name) = switch (field.type) {
12366 u32 => value,
12367 MetadataString, Metadata, Variable.Index, Value => @enumFromInt(value),
12368 else => @compileError("bad field type: " ++ @typeName(field.type)),
12369 };
12370 return .{
12371 .data = result,
12372 .trail = .{ .index = index + @as(Metadata.Item.ExtraIndex, @intCast(fields.len)) },
12373 };
12374}
12375
12376fn metadataExtraData(self: *const Builder, comptime T: type, index: Metadata.Item.ExtraIndex) T {
12377 return self.metadataExtraDataTrail(T, index).data;
12378}
12379
12380fn metadataString(self: *Builder, str: String) Allocator.Error!MetadataString {
12381 const gop = try self.metadata_strings.getOrPut(self.gpa, str);
12382 if (!gop.found_existing) gop.key_ptr.* = str;
12383
12384 return @enumFromInt(gop.index);
12385}
12386
12387pub fn debugNamed(self: *Builder, name: String, operands: []const Metadata) Allocator.Error!void {
12388 try self.metadata_extra.ensureUnusedCapacity(
12389 self.gpa,
12390 operands.len * @sizeOf(Metadata),
12391 );
12392 try self.metadata_named.ensureUnusedCapacity(self.gpa, 1);
12393 self.debugNamedAssumeCapacity(name, operands);
12394}
12395
12396fn debugNone(self: *Builder) Allocator.Error!Metadata {
12397 try self.ensureUnusedMetadataCapacity(1, NoExtra, 0);
12398 return self.debugNoneAssumeCapacity();
12399}
12400
12401pub fn debugFile(self: *Builder, path: String, name: String) Allocator.Error!Metadata {
12402 try self.ensureUnusedMetadataCapacity(1, Metadata.File, 0);
12403 const metadata_path = try self.metadataString(path);
12404 const metadata_name = try self.metadataString(name);
12405 return self.debugFileAssumeCapacity(metadata_path, metadata_name);
12406}
12407
12408pub fn debugCompileUnit(
12409 self: *Builder,
12410 file: Metadata,
12411 producer: String,
12412 enums: Metadata,
12413 globals: Metadata,
12414 flags: Metadata.CompileUnit.Flags,
12415) Allocator.Error!Metadata {
12416 try self.ensureUnusedMetadataCapacity(1, Metadata.CompileUnit, 0);
12417 const metadata_producer = try self.metadataString(producer);
12418 return self.debugCompileUnitAssumeCapacity(file, metadata_producer, enums, globals, flags);
12419}
12420
12421pub fn debugSubprogram(
12422 self: *Builder,
12423 file: Metadata,
12424 name: String,
12425 linkage_name: String,
12426 line: u32,
12427 scope_line: u32,
12428 ty: Metadata,
12429 flags: Metadata.Subprogram.Flags,
12430 compile_unit: Metadata,
12431) Allocator.Error!Metadata {
12432 try self.ensureUnusedMetadataCapacity(1, Metadata.Subprogram, 0);
12433 const metadata_name = try self.metadataString(name);
12434 const metadata_linkage_name = try self.metadataString(linkage_name);
12435 return self.debugSubprogramAssumeCapacity(
12436 file,
12437 metadata_name,
12438 metadata_linkage_name,
12439 line,
12440 scope_line,
12441 ty,
12442 flags,
12443 compile_unit,
12444 );
12445}
12446
12447pub fn debugLexicalBlock(self: *Builder, file: Metadata, scope: Metadata, line: u32, column: u32) Allocator.Error!Metadata {
12448 try self.ensureUnusedMetadataCapacity(1, Metadata.LexicalBlock, 0);
12449 return self.debugLexicalBlockAssumeCapacity(file, scope, line, column);
12450}
12451
12452pub fn debugLocation(self: *Builder, scope: Metadata, line: u32, column: u32, inlined_at: Metadata) Allocator.Error!Metadata {
12453 try self.ensureUnusedMetadataCapacity(1, Metadata.Location, 0);
12454 return self.debugLocationAssumeCapacity(scope, line, column, inlined_at);
12455}
12456
12457pub fn debugBoolType(self: *Builder, name: String, size_in_bits: u64) Allocator.Error!Metadata {
12458 try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0);
12459 const metadata_name = try self.metadataString(name);
12460 return self.debugBoolTypeAssumeCapacity(metadata_name, size_in_bits);
12461}
12462
12463pub fn debugUnsignedType(self: *Builder, name: String, size_in_bits: u64) Allocator.Error!Metadata {
12464 try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0);
12465 const metadata_name = try self.metadataString(name);
12466 return self.debugUnsignedTypeAssumeCapacity(metadata_name, size_in_bits);
12467}
12468
12469pub fn debugSignedType(self: *Builder, name: String, size_in_bits: u64) Allocator.Error!Metadata {
12470 try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0);
12471 const metadata_name = try self.metadataString(name);
12472 return self.debugSignedTypeAssumeCapacity(metadata_name, size_in_bits);
12473}
12474
12475pub fn debugFloatType(self: *Builder, name: String, size_in_bits: u64) Allocator.Error!Metadata {
12476 try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0);
12477 const metadata_name = try self.metadataString(name);
12478 return self.debugFloatTypeAssumeCapacity(metadata_name, size_in_bits);
12479}
12480
12481pub fn debugForwardReference(self: *Builder) Allocator.Error!Metadata {
12482 try self.metadata_forward_references.ensureUnusedCapacity(self.gpa, 1);
12483 return self.debugForwardReferenceAssumeCapacity();
12484}
12485
12486pub fn debugStructType(
12487 self: *Builder,
12488 name: String,
12489 file: Metadata,
12490 scope: Metadata,
12491 line: u32,
12492 underlying_type: Metadata,
12493 size_in_bits: u64,
12494 align_in_bits: u64,
12495 fields_tuple: Metadata,
12496) Allocator.Error!Metadata {
12497 try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
12498 const metadata_name = try self.metadataString(name);
12499 return self.debugStructTypeAssumeCapacity(
12500 metadata_name,
12501 file,
12502 scope,
12503 line,
12504 underlying_type,
12505 size_in_bits,
12506 align_in_bits,
12507 fields_tuple,
12508 );
12509}
12510
12511pub fn debugUnionType(
12512 self: *Builder,
12513 name: String,
12514 file: Metadata,
12515 scope: Metadata,
12516 line: u32,
12517 underlying_type: Metadata,
12518 size_in_bits: u64,
12519 align_in_bits: u64,
12520 fields_tuple: Metadata,
12521) Allocator.Error!Metadata {
12522 try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
12523 const metadata_name = try self.metadataString(name);
12524 return self.debugUnionTypeAssumeCapacity(
12525 metadata_name,
12526 file,
12527 scope,
12528 line,
12529 underlying_type,
12530 size_in_bits,
12531 align_in_bits,
12532 fields_tuple,
12533 );
12534}
12535
12536pub fn debugEnumerationType(
12537 self: *Builder,
12538 name: String,
12539 file: Metadata,
12540 scope: Metadata,
12541 line: u32,
12542 underlying_type: Metadata,
12543 size_in_bits: u64,
12544 align_in_bits: u64,
12545 fields_tuple: Metadata,
12546) Allocator.Error!Metadata {
12547 try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
12548 const metadata_name = try self.metadataString(name);
12549 return self.debugEnumerationTypeAssumeCapacity(
12550 metadata_name,
12551 file,
12552 scope,
12553 line,
12554 underlying_type,
12555 size_in_bits,
12556 align_in_bits,
12557 fields_tuple,
12558 );
12559}
12560
12561pub fn debugArrayType(
12562 self: *Builder,
12563 name: String,
12564 file: Metadata,
12565 scope: Metadata,
12566 line: u32,
12567 underlying_type: Metadata,
12568 size_in_bits: u64,
12569 align_in_bits: u64,
12570 fields_tuple: Metadata,
12571) Allocator.Error!Metadata {
12572 try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
12573 const metadata_name = try self.metadataString(name);
12574 return self.debugArrayTypeAssumeCapacity(
12575 metadata_name,
12576 file,
12577 scope,
12578 line,
12579 underlying_type,
12580 size_in_bits,
12581 align_in_bits,
12582 fields_tuple,
12583 );
12584}
12585
12586pub fn debugPointerType(
12587 self: *Builder,
12588 name: String,
12589 file: Metadata,
12590 scope: Metadata,
12591 line: u32,
12592 underlying_type: Metadata,
12593 size_in_bits: u64,
12594 align_in_bits: u64,
12595 offset_in_bits: u64,
12596) Allocator.Error!Metadata {
12597 try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0);
12598 const metadata_name = try self.metadataString(name);
12599 return self.debugPointerTypeAssumeCapacity(
12600 metadata_name,
12601 file,
12602 scope,
12603 line,
12604 underlying_type,
12605 size_in_bits,
12606 align_in_bits,
12607 offset_in_bits,
12608 );
12609}
12610
12611pub fn debugMemberType(
12612 self: *Builder,
12613 name: String,
12614 file: Metadata,
12615 scope: Metadata,
12616 line: u32,
12617 underlying_type: Metadata,
12618 size_in_bits: u64,
12619 align_in_bits: u64,
12620 offset_in_bits: u64,
12621) Allocator.Error!Metadata {
12622 try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0);
12623 const metadata_name = try self.metadataString(name);
12624 return self.debugMemberTypeAssumeCapacity(
12625 metadata_name,
12626 file,
12627 scope,
12628 line,
12629 underlying_type,
12630 size_in_bits,
12631 align_in_bits,
12632 offset_in_bits,
12633 );
12634}
12635
12636pub fn debugSubroutineType(
12637 self: *Builder,
12638 types_tuple: Metadata,
12639) Allocator.Error!Metadata {
12640 try self.ensureUnusedMetadataCapacity(1, Metadata.SubroutineType, 0);
12641 return self.debugSubroutineTypeAssumeCapacity(types_tuple);
12642}
12643
12644pub fn debugEnumerator(
12645 self: *Builder,
12646 name: String,
12647 unsigned: bool,
12648 bit_width: u32,
12649 value: std.math.big.int.Const,
12650) Allocator.Error!Metadata {
12651 std.debug.assert(!(unsigned and !value.positive));
12652 try self.ensureUnusedMetadataCapacity(1, Metadata.Enumerator, 0);
12653 try self.metadata_limbs.ensureUnusedCapacity(self.gpa, value.limbs.len);
12654 const metadata_name = try self.metadataString(name);
12655 return self.debugEnumeratorAssumeCapacity(metadata_name, unsigned, bit_width, value);
12656}
12657
12658pub fn debugSubrange(
12659 self: *Builder,
12660 lower_bound: Metadata,
12661 count: Metadata,
12662) Allocator.Error!Metadata {
12663 try self.ensureUnusedMetadataCapacity(1, Metadata.Subrange, 0);
12664 return self.debugSubrangeAssumeCapacity(lower_bound, count);
12665}
12666
12667pub fn debugExpression(
12668 self: *Builder,
12669 elements: []const u32,
12670) Allocator.Error!Metadata {
12671 try self.ensureUnusedMetadataCapacity(1, Metadata.Expression, elements.len * @sizeOf(u32));
12672 return self.debugExpressionAssumeCapacity(elements);
12673}
12674
12675pub fn debugTuple(
12676 self: *Builder,
12677 elements: []const Metadata,
12678) Allocator.Error!Metadata {
12679 try self.ensureUnusedMetadataCapacity(1, Metadata.Tuple, elements.len * @sizeOf(Metadata));
12680 return self.debugTupleAssumeCapacity(elements);
12681}
12682
12683pub fn debugModuleFlag(
12684 self: *Builder,
12685 behaviour: Metadata,
12686 name: String,
12687 constant: Metadata,
12688) Allocator.Error!Metadata {
12689 try self.ensureUnusedMetadataCapacity(1, Metadata.ModuleFlag, 0);
12690 const metadata_name = try self.metadataString(name);
12691 return self.debugModuleFlagAssumeCapacity(behaviour, metadata_name, constant);
12692}
12693
12694pub fn debugLocalVar(
12695 self: *Builder,
12696 name: String,
12697 file: Metadata,
12698 scope: Metadata,
12699 line: u32,
12700 ty: Metadata,
12701) Allocator.Error!Metadata {
12702 try self.ensureUnusedMetadataCapacity(1, Metadata.LocalVar, 0);
12703 const metadata_name = try self.metadataString(name);
12704 return self.debugLocalVarAssumeCapacity(metadata_name, file, scope, line, ty);
12705}
12706
12707pub fn debugParameter(
12708 self: *Builder,
12709 name: String,
12710 file: Metadata,
12711 scope: Metadata,
12712 line: u32,
12713 ty: Metadata,
12714 arg_no: u32,
12715) Allocator.Error!Metadata {
12716 try self.ensureUnusedMetadataCapacity(1, Metadata.Parameter, 0);
12717 const metadata_name = try self.metadataString(name);
12718 return self.debugParameterAssumeCapacity(metadata_name, file, scope, line, ty, arg_no);
12719}
12720
12721pub fn debugGlobalVar(
12722 self: *Builder,
12723 name: String,
12724 linkage_name: String,
12725 file: Metadata,
12726 scope: Metadata,
12727 line: u32,
12728 ty: Metadata,
12729 variable: Variable.Index,
12730 flags: Metadata.GlobalVar.Flags,
12731) Allocator.Error!Metadata {
12732 try self.ensureUnusedMetadataCapacity(1, Metadata.GlobalVar, 0);
12733 const metadata_name = try self.metadataString(name);
12734 const metadata_linkage_name = try self.metadataString(linkage_name);
12735 return self.debugGlobalVarAssumeCapacity(
12736 metadata_name,
12737 metadata_linkage_name,
12738 file,
12739 scope,
12740 line,
12741 ty,
12742 variable,
12743 flags,
12744 );
12745}
12746
12747pub fn debugGlobalVarExpression(
12748 self: *Builder,
12749 variable: Metadata,
12750 expression: Metadata,
12751) Allocator.Error!Metadata {
12752 try self.ensureUnusedMetadataCapacity(1, Metadata.GlobalVarExpression, 0);
12753 return self.debugGlobalVarExpressionAssumeCapacity(variable, expression);
12754}
12755
12756pub fn debugConstant(self: *Builder, value: Constant) Allocator.Error!Metadata {
12757 try self.ensureUnusedMetadataCapacity(1, NoExtra, 0);
12758 return self.debugConstantAssumeCapacity(value);
12759}
12760
12761pub fn debugForwardReferenceSetType(self: *Builder, fwd_ref: Metadata, ty: Metadata) void {
12762 std.debug.assert(
12763 @intFromEnum(fwd_ref) >= Metadata.first_forward_reference and
12764 @intFromEnum(fwd_ref) <= Metadata.first_local_metadata,
12765 );
12766 const index = @intFromEnum(fwd_ref) - Metadata.first_forward_reference;
12767 self.metadata_forward_references.items[index] = ty;
12768}
12769
12770fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytype) Metadata {
12771 const Key = struct {
12772 tag: Metadata.Tag,
12773 value: @TypeOf(value),
12774 };
12775 const Adapter = struct {
12776 builder: *const Builder,
12777 pub fn hash(_: @This(), key: Key) u32 {
12778 var hasher = std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(key.tag)));
12779 inline for (std.meta.fields(@TypeOf(value))) |field| {
12780 hasher.update(std.mem.asBytes(&@field(key.value, field.name)));
12781 }
12782 return @truncate(hasher.final());
12783 }
12784
12785 pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
12786 if (lhs_key.tag != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
12787 const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index];
12788 const rhs_extra = ctx.builder.metadataExtraData(@TypeOf(value), rhs_data);
12789 inline for (std.meta.fields(@TypeOf(value))) |field| {
12790 const lhs = @field(lhs_key.value, field.name);
12791 const rhs = @field(rhs_extra, field.name);
12792 if (lhs != rhs) return false;
12793 }
12794 return true;
12795 }
12796 };
12797
12798 const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
12799 Key{ .tag = tag, .value = value },
12800 Adapter{ .builder = self },
12801 );
12802
12803 if (!gop.found_existing) {
12804 gop.key_ptr.* = {};
12805 gop.value_ptr.* = {};
12806 self.metadata_items.appendAssumeCapacity(.{
12807 .tag = tag,
12808 .data = self.addMetadataExtraAssumeCapacity(value),
12809 });
12810 }
12811 return @enumFromInt(gop.index);
12812}
12813
12814fn debugNamedAssumeCapacity(self: *Builder, name: String, operands: []const Metadata) void {
12815 const extra_index: u32 = @intCast(self.metadata_extra.items.len);
12816 self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(operands));
12817
12818 const gop = self.metadata_named.getOrPutAssumeCapacity(name);
12819 gop.value_ptr.* = .{
12820 .index = extra_index,
12821 .len = @intCast(operands.len),
12822 };
12823}
12824
12825pub fn debugNoneAssumeCapacity(self: *Builder) Metadata {
12826 return self.metadataSimpleAssumeCapacity(.none, .{});
12827}
12828
12829fn debugFileAssumeCapacity(self: *Builder, path: MetadataString, name: MetadataString) Metadata {
12830 return self.metadataSimpleAssumeCapacity(.file, Metadata.File{
12831 .path = path,
12832 .name = name,
12833 });
12834}
12835
12836pub fn debugCompileUnitAssumeCapacity(
12837 self: *Builder,
12838 file: Metadata,
12839 producer: MetadataString,
12840 enums: Metadata,
12841 globals: Metadata,
12842 flags: Metadata.CompileUnit.Flags,
12843) Metadata {
12844 return self.metadataSimpleAssumeCapacity(
12845 if (flags.optimized) .@"compile_unit optimized" else .compile_unit,
12846 Metadata.CompileUnit{
12847 .file = file,
12848 .producer = producer,
12849 .enums = enums,
12850 .globals = globals,
12851 },
12852 );
12853}
12854
12855fn debugSubprogramAssumeCapacity(
12856 self: *Builder,
12857 file: Metadata,
12858 name: MetadataString,
12859 linkage_name: MetadataString,
12860 line: u32,
12861 scope_line: u32,
12862 ty: Metadata,
12863 flags: Metadata.Subprogram.Flags,
12864 compile_unit: Metadata,
12865) Metadata {
12866 const tag: Metadata.Tag = blk: {
12867 var int: u3 = 0;
12868 if (flags.optimized) int |= 0b1;
12869 if (flags.local) int |= 0b10;
12870 if (flags.definition) int |= 0b100;
12871 break :blk switch (int) {
12872 0 => .subprogram,
12873 0b1 => .@"subprogram optimized",
12874 0b10 => .@"subprogram local",
12875 0b100 => .@"subprogram definition",
12876 0b011 => .@"subprogram optimized local",
12877 0b111 => .@"subprogram optimized local definition",
12878 0b101 => .@"subprogram optimized definition",
12879 0b110 => .@"subprogram local definition",
12880 };
12881 };
12882 return self.metadataSimpleAssumeCapacity(tag, Metadata.Subprogram{
12883 .file = file,
12884 .name = name,
12885 .linkage_name = linkage_name,
12886 .line = line,
12887 .scope_line = scope_line,
12888 .ty = ty,
12889 .debug_info_flags = flags.debug_info_flags,
12890 .compile_unit = compile_unit,
12891 });
12892}
12893
12894fn debugLexicalBlockAssumeCapacity(self: *Builder, file: Metadata, scope: Metadata, line: u32, column: u32) Metadata {
12895 return self.metadataSimpleAssumeCapacity(.lexical_block, Metadata.LexicalBlock{
12896 .file = file,
12897 .scope = scope,
12898 .line = line,
12899 .column = column,
12900 });
12901}
12902
12903fn debugLocationAssumeCapacity(self: *Builder, scope: Metadata, line: u32, column: u32, inlined_at: Metadata) Metadata {
12904 return self.metadataSimpleAssumeCapacity(.location, Metadata.Location{
12905 .scope = scope,
12906 .line = line,
12907 .column = column,
12908 .inlined_at = inlined_at,
12909 });
12910}
12911
12912fn debugBoolTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata {
12913 return self.metadataSimpleAssumeCapacity(.basic_bool_type, Metadata.BasicType{
12914 .name = name,
12915 .size_in_bits_lo = @truncate(size_in_bits),
12916 .size_in_bits_hi = @truncate(size_in_bits >> 32),
12917 });
12918}
12919
12920fn debugUnsignedTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata {
12921 return self.metadataSimpleAssumeCapacity(.basic_unsigned_type, Metadata.BasicType{
12922 .name = name,
12923 .size_in_bits_lo = @truncate(size_in_bits),
12924 .size_in_bits_hi = @truncate(size_in_bits >> 32),
12925 });
12926}
12927
12928fn debugSignedTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata {
12929 return self.metadataSimpleAssumeCapacity(.basic_signed_type, Metadata.BasicType{
12930 .name = name,
12931 .size_in_bits_lo = @truncate(size_in_bits),
12932 .size_in_bits_hi = @truncate(size_in_bits >> 32),
12933 });
12934}
12935
12936fn debugFloatTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata {
12937 return self.metadataSimpleAssumeCapacity(.basic_float_type, Metadata.BasicType{
12938 .name = name,
12939 .size_in_bits_lo = @truncate(size_in_bits),
12940 .size_in_bits_hi = @truncate(size_in_bits >> 32),
12941 });
12942}
12943
12944fn debugForwardReferenceAssumeCapacity(self: *Builder) Metadata {
12945 const index = Metadata.first_forward_reference + self.metadata_forward_references.items.len;
12946 self.metadata_forward_references.appendAssumeCapacity(.none);
12947 return @enumFromInt(index);
12948}
12949
12950fn debugStructTypeAssumeCapacity(
12951 self: *Builder,
12952 name: MetadataString,
12953 file: Metadata,
12954 scope: Metadata,
12955 line: u32,
12956 underlying_type: Metadata,
12957 size_in_bits: u64,
12958 align_in_bits: u64,
12959 fields_tuple: Metadata,
12960) Metadata {
12961 return self.debugCompositeTypeAssumeCapacity(
12962 .composite_struct_type,
12963 name,
12964 file,
12965 scope,
12966 line,
12967 underlying_type,
12968 size_in_bits,
12969 align_in_bits,
12970 fields_tuple,
12971 );
12972}
12973
12974fn debugUnionTypeAssumeCapacity(
12975 self: *Builder,
12976 name: MetadataString,
12977 file: Metadata,
12978 scope: Metadata,
12979 line: u32,
12980 underlying_type: Metadata,
12981 size_in_bits: u64,
12982 align_in_bits: u64,
12983 fields_tuple: Metadata,
12984) Metadata {
12985 return self.debugCompositeTypeAssumeCapacity(
12986 .composite_union_type,
12987 name,
12988 file,
12989 scope,
12990 line,
12991 underlying_type,
12992 size_in_bits,
12993 align_in_bits,
12994 fields_tuple,
12995 );
12996}
12997
12998fn debugEnumerationTypeAssumeCapacity(
12999 self: *Builder,
13000 name: MetadataString,
13001 file: Metadata,
13002 scope: Metadata,
13003 line: u32,
13004 underlying_type: Metadata,
13005 size_in_bits: u64,
13006 align_in_bits: u64,
13007 fields_tuple: Metadata,
13008) Metadata {
13009 return self.debugCompositeTypeAssumeCapacity(
13010 .composite_enumeration_type,
13011 name,
13012 file,
13013 scope,
13014 line,
13015 underlying_type,
13016 size_in_bits,
13017 align_in_bits,
13018 fields_tuple,
13019 );
13020}
13021
13022fn debugArrayTypeAssumeCapacity(
13023 self: *Builder,
13024 name: MetadataString,
13025 file: Metadata,
13026 scope: Metadata,
13027 line: u32,
13028 underlying_type: Metadata,
13029 size_in_bits: u64,
13030 align_in_bits: u64,
13031 fields_tuple: Metadata,
13032) Metadata {
13033 return self.debugCompositeTypeAssumeCapacity(
13034 .composite_array_type,
13035 name,
13036 file,
13037 scope,
13038 line,
13039 underlying_type,
13040 size_in_bits,
13041 align_in_bits,
13042 fields_tuple,
13043 );
13044}
13045
13046fn debugCompositeTypeAssumeCapacity(
13047 self: *Builder,
13048 tag: Metadata.Tag,
13049 name: MetadataString,
13050 file: Metadata,
13051 scope: Metadata,
13052 line: u32,
13053 underlying_type: Metadata,
13054 size_in_bits: u64,
13055 align_in_bits: u64,
13056 fields_tuple: Metadata,
13057) Metadata {
13058 const Key = struct {
13059 tag: Metadata.Tag,
13060 name: MetadataString,
13061 file: Metadata,
13062 scope: Metadata,
13063 line: u32,
13064 underlying_type: Metadata,
13065 size_in_bits: u64,
13066 align_in_bits: u64,
13067 fields_tuple: Metadata,
13068 };
13069 const Adapter = struct {
13070 builder: *const Builder,
13071 pub fn hash(_: @This(), key: Key) u32 {
13072 var hasher = std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(key.tag)));
13073 hasher.update(std.mem.asBytes(&key.name));
13074 hasher.update(std.mem.asBytes(&key.file));
13075 hasher.update(std.mem.asBytes(&key.scope));
13076 hasher.update(std.mem.asBytes(&key.line));
13077 hasher.update(std.mem.asBytes(&key.underlying_type));
13078 hasher.update(std.mem.asBytes(&key.size_in_bits));
13079 hasher.update(std.mem.asBytes(&key.align_in_bits));
13080 hasher.update(std.mem.asBytes(&key.fields_tuple));
13081 return @truncate(hasher.final());
13082 }
13083
13084 pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
13085 if (lhs_key.tag != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
13086 const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index];
13087 const rhs_extra = ctx.builder.metadataExtraData(Metadata.CompositeType, rhs_data);
13088 const rhs_size_in_bits = @as(u64, rhs_extra.size_in_bits_lo) | @as(u64, rhs_extra.size_in_bits_hi) << 32;
13089 const rhs_align_in_bits = @as(u64, rhs_extra.align_in_bits_lo) | @as(u64, rhs_extra.align_in_bits_hi) << 32;
13090 return lhs_key.name == rhs_extra.name and
13091 lhs_key.file == rhs_extra.file and
13092 lhs_key.scope == rhs_extra.scope and
13093 lhs_key.line == rhs_extra.line and
13094 lhs_key.underlying_type == rhs_extra.underlying_type and
13095 lhs_key.size_in_bits == rhs_size_in_bits and
13096 lhs_key.align_in_bits == rhs_align_in_bits and
13097 lhs_key.fields_tuple == rhs_extra.fields_tuple;
13098 }
13099 };
13100
13101 const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
13102 Key{
13103 .tag = tag,
13104 .name = name,
13105 .file = file,
13106 .scope = scope,
13107 .line = line,
13108 .underlying_type = underlying_type,
13109 .size_in_bits = size_in_bits,
13110 .align_in_bits = align_in_bits,
13111 .fields_tuple = fields_tuple,
13112 },
13113 Adapter{ .builder = self },
13114 );
13115
13116 if (!gop.found_existing) {
13117 gop.key_ptr.* = {};
13118 gop.value_ptr.* = {};
13119 self.metadata_items.appendAssumeCapacity(.{
13120 .tag = tag,
13121 .data = self.addMetadataExtraAssumeCapacity(Metadata.CompositeType{
13122 .name = name,
13123 .file = file,
13124 .scope = scope,
13125 .line = line,
13126 .underlying_type = underlying_type,
13127 .size_in_bits_lo = @truncate(size_in_bits),
13128 .size_in_bits_hi = @truncate(size_in_bits >> 32),
13129 .align_in_bits_lo = @truncate(align_in_bits),
13130 .align_in_bits_hi = @truncate(align_in_bits >> 32),
13131 .fields_tuple = fields_tuple,
13132 }),
13133 });
13134 }
13135 return @enumFromInt(gop.index);
13136}
13137
13138fn debugPointerTypeAssumeCapacity(
13139 self: *Builder,
13140 name: MetadataString,
13141 file: Metadata,
13142 scope: Metadata,
13143 line: u32,
13144 underlying_type: Metadata,
13145 size_in_bits: u64,
13146 align_in_bits: u64,
13147 offset_in_bits: u64,
13148) Metadata {
13149 return self.metadataSimpleAssumeCapacity(.derived_pointer_type, Metadata.DerivedType{
13150 .name = name,
13151 .file = file,
13152 .scope = scope,
13153 .line = line,
13154 .underlying_type = underlying_type,
13155 .size_in_bits_lo = @truncate(size_in_bits),
13156 .size_in_bits_hi = @truncate(size_in_bits >> 32),
13157 .align_in_bits_lo = @truncate(align_in_bits),
13158 .align_in_bits_hi = @truncate(align_in_bits >> 32),
13159 .offset_in_bits_lo = @truncate(offset_in_bits),
13160 .offset_in_bits_hi = @truncate(offset_in_bits >> 32),
13161 });
13162}
13163
13164fn debugMemberTypeAssumeCapacity(
13165 self: *Builder,
13166 name: MetadataString,
13167 file: Metadata,
13168 scope: Metadata,
13169 line: u32,
13170 underlying_type: Metadata,
13171 size_in_bits: u64,
13172 align_in_bits: u64,
13173 offset_in_bits: u64,
13174) Metadata {
13175 return self.metadataSimpleAssumeCapacity(.derived_member_type, Metadata.DerivedType{
13176 .name = name,
13177 .file = file,
13178 .scope = scope,
13179 .line = line,
13180 .underlying_type = underlying_type,
13181 .size_in_bits_lo = @truncate(size_in_bits),
13182 .size_in_bits_hi = @truncate(size_in_bits >> 32),
13183 .align_in_bits_lo = @truncate(align_in_bits),
13184 .align_in_bits_hi = @truncate(align_in_bits >> 32),
13185 .offset_in_bits_lo = @truncate(offset_in_bits),
13186 .offset_in_bits_hi = @truncate(offset_in_bits >> 32),
13187 });
13188}
13189
13190fn debugSubroutineTypeAssumeCapacity(
13191 self: *Builder,
13192 types_tuple: Metadata,
13193) Metadata {
13194 return self.metadataSimpleAssumeCapacity(.subroutine_type, Metadata.SubroutineType{
13195 .types_tuple = types_tuple,
13196 });
13197}
13198
13199fn debugEnumeratorAssumeCapacity(
13200 self: *Builder,
13201 name: MetadataString,
13202 unsigned: bool,
13203 bit_width: u32,
13204 value: std.math.big.int.Const,
13205) Metadata {
13206 const Key = struct {
13207 tag: Metadata.Tag,
13208 name: MetadataString,
13209 bit_width: u32,
13210 value: std.math.big.int.Const,
13211 };
13212 const Adapter = struct {
13213 builder: *const Builder,
13214 pub fn hash(_: @This(), key: Key) u32 {
13215 var hasher = std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(key.tag)));
13216 hasher.update(std.mem.asBytes(&key.name));
13217 hasher.update(std.mem.asBytes(&key.bit_width));
13218 hasher.update(std.mem.sliceAsBytes(key.value.limbs));
13219 return @truncate(hasher.final());
13220 }
13221
13222 pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
13223 if (lhs_key.tag != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
13224 const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index];
13225 const rhs_extra = ctx.builder.metadataExtraData(Metadata.Enumerator, rhs_data);
13226 const limbs = ctx.builder.metadata_limbs
13227 .items[rhs_extra.limbs_index..][0..rhs_extra.limbs_len];
13228 const rhs_value = std.math.big.int.Const{
13229 .limbs = limbs,
13230 .positive = lhs_key.value.positive,
13231 };
13232 return lhs_key.name == rhs_extra.name and
13233 lhs_key.bit_width == rhs_extra.bit_width and
13234 lhs_key.value.eql(rhs_value);
13235 }
13236 };
13237
13238 const tag: Metadata.Tag = if (unsigned)
13239 .enumerator_unsigned
13240 else if (value.positive) .enumerator_signed_positive else .enumerator_signed_negative;
13241
13242 std.debug.assert(!(tag == .enumerator_unsigned and !value.positive));
13243
13244 const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
13245 Key{
13246 .tag = tag,
13247 .name = name,
13248 .bit_width = bit_width,
13249 .value = value,
13250 },
13251 Adapter{ .builder = self },
13252 );
13253
13254 if (!gop.found_existing) {
13255 gop.key_ptr.* = {};
13256 gop.value_ptr.* = {};
13257 self.metadata_items.appendAssumeCapacity(.{
13258 .tag = tag,
13259 .data = self.addMetadataExtraAssumeCapacity(Metadata.Enumerator{
13260 .name = name,
13261 .bit_width = bit_width,
13262 .limbs_index = @intCast(self.metadata_limbs.items.len),
13263 .limbs_len = @intCast(value.limbs.len),
13264 }),
13265 });
13266 self.metadata_limbs.appendSliceAssumeCapacity(value.limbs);
13267 }
13268 return @enumFromInt(gop.index);
13269}
13270
13271fn debugSubrangeAssumeCapacity(
13272 self: *Builder,
13273 lower_bound: Metadata,
13274 count: Metadata,
13275) Metadata {
13276 return self.metadataSimpleAssumeCapacity(.subrange, Metadata.Subrange{
13277 .lower_bound = lower_bound,
13278 .count = count,
13279 });
13280}
13281
13282fn debugExpressionAssumeCapacity(
13283 self: *Builder,
13284 elements: []const u32,
13285) Metadata {
13286 const Key = struct {
13287 elements: []const u32,
13288 };
13289 const Adapter = struct {
13290 builder: *const Builder,
13291 pub fn hash(_: @This(), key: Key) u32 {
13292 var hasher = comptime std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(Metadata.Tag.expression)));
13293 hasher.update(std.mem.sliceAsBytes(key.elements));
13294 return @truncate(hasher.final());
13295 }
13296
13297 pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
13298 if (Metadata.Tag.expression != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
13299 const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index];
13300 var rhs_extra = ctx.builder.metadataExtraDataTrail(Metadata.Expression, rhs_data);
13301 return std.mem.eql(
13302 u32,
13303 lhs_key.elements,
13304 rhs_extra.trail.next(rhs_extra.data.elements_len, u32, ctx.builder),
13305 );
13306 }
13307 };
13308
13309 const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
13310 Key{ .elements = elements },
13311 Adapter{ .builder = self },
13312 );
13313
13314 if (!gop.found_existing) {
13315 gop.key_ptr.* = {};
13316 gop.value_ptr.* = {};
13317 self.metadata_items.appendAssumeCapacity(.{
13318 .tag = .expression,
13319 .data = self.addMetadataExtraAssumeCapacity(Metadata.Expression{
13320 .elements_len = @intCast(elements.len),
13321 }),
13322 });
13323 self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(elements));
13324 }
13325 return @enumFromInt(gop.index);
13326}
13327
13328fn debugTupleAssumeCapacity(
13329 self: *Builder,
13330 elements: []const Metadata,
13331) Metadata {
13332 const Key = struct {
13333 elements: []const Metadata,
13334 };
13335 const Adapter = struct {
13336 builder: *const Builder,
13337 pub fn hash(_: @This(), key: Key) u32 {
13338 var hasher = comptime std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(Metadata.Tag.tuple)));
13339 hasher.update(std.mem.sliceAsBytes(key.elements));
13340 return @truncate(hasher.final());
13341 }
13342
13343 pub fn eql(ctx: @This(), lhs_key: Key, _: void, rhs_index: usize) bool {
13344 if (Metadata.Tag.tuple != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
13345 const rhs_data = ctx.builder.metadata_items.items(.data)[rhs_index];
13346 var rhs_extra = ctx.builder.metadataExtraDataTrail(Metadata.Tuple, rhs_data);
13347 return std.mem.eql(
13348 Metadata,
13349 lhs_key.elements,
13350 rhs_extra.trail.next(rhs_extra.data.elements_len, Metadata, ctx.builder),
13351 );
13352 }
13353 };
13354
13355 const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
13356 Key{ .elements = elements },
13357 Adapter{ .builder = self },
13358 );
13359
13360 if (!gop.found_existing) {
13361 gop.key_ptr.* = {};
13362 gop.value_ptr.* = {};
13363 self.metadata_items.appendAssumeCapacity(.{
13364 .tag = .tuple,
13365 .data = self.addMetadataExtraAssumeCapacity(Metadata.Tuple{
13366 .elements_len = @intCast(elements.len),
13367 }),
13368 });
13369 self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(elements));
13370 }
13371 return @enumFromInt(gop.index);
13372}
13373
13374fn debugModuleFlagAssumeCapacity(
13375 self: *Builder,
13376 behaviour: Metadata,
13377 name: MetadataString,
13378 constant: Metadata,
13379) Metadata {
13380 return self.metadataSimpleAssumeCapacity(.module_flag, Metadata.ModuleFlag{
13381 .behaviour = behaviour,
13382 .name = name,
13383 .constant = constant,
13384 });
13385}
13386
13387fn debugLocalVarAssumeCapacity(
13388 self: *Builder,
13389 name: MetadataString,
13390 file: Metadata,
13391 scope: Metadata,
13392 line: u32,
13393 ty: Metadata,
13394) Allocator.Error!Metadata {
13395 return self.metadataSimpleAssumeCapacity(.local_var, Metadata.LocalVar{
13396 .name = name,
13397 .file = file,
13398 .scope = scope,
13399 .line = line,
13400 .ty = ty,
13401 });
13402}
13403
13404fn debugParameterAssumeCapacity(
13405 self: *Builder,
13406 name: MetadataString,
13407 file: Metadata,
13408 scope: Metadata,
13409 line: u32,
13410 ty: Metadata,
13411 arg_no: u32,
13412) Allocator.Error!Metadata {
13413 return self.metadataSimpleAssumeCapacity(.parameter, Metadata.Parameter{
13414 .name = name,
13415 .file = file,
13416 .scope = scope,
13417 .line = line,
13418 .ty = ty,
13419 .arg_no = arg_no,
13420 });
13421}
13422
13423fn debugGlobalVarAssumeCapacity(
13424 self: *Builder,
13425 name: MetadataString,
13426 linkage_name: MetadataString,
13427 file: Metadata,
13428 scope: Metadata,
13429 line: u32,
13430 ty: Metadata,
13431 variable: Variable.Index,
13432 flags: Metadata.GlobalVar.Flags,
13433) Allocator.Error!Metadata {
13434 return self.metadataSimpleAssumeCapacity(
13435 if (flags.local) .@"global_var local" else .global_var,
13436 Metadata.GlobalVar{
13437 .name = name,
13438 .linkage_name = linkage_name,
13439 .file = file,
13440 .scope = scope,
13441 .line = line,
13442 .ty = ty,
13443 .variable = variable,
13444 },
13445 );
13446}
13447
13448fn debugGlobalVarExpressionAssumeCapacity(
13449 self: *Builder,
13450 variable: Metadata,
13451 expression: Metadata,
13452) Metadata {
13453 return self.metadataSimpleAssumeCapacity(.global_var_expression, Metadata.GlobalVarExpression{
13454 .variable = variable,
13455 .expression = expression,
13456 });
13457}
13458
13459fn debugConstantAssumeCapacity(self: *Builder, constant: Constant) Metadata {
13460 const Adapter = struct {
13461 builder: *const Builder,
13462 pub fn hash(_: @This(), key: Constant) u32 {
13463 var hasher = comptime std.hash.Wyhash.init(std.hash.uint32(@intFromEnum(Metadata.Tag.constant)));
13464 hasher.update(std.mem.asBytes(&key));
13465 return @truncate(hasher.final());
13466 }
13467
13468 pub fn eql(ctx: @This(), lhs_key: Constant, _: void, rhs_index: usize) bool {
13469 if (Metadata.Tag.constant != ctx.builder.metadata_items.items(.tag)[rhs_index]) return false;
13470 const rhs_data: Constant = @enumFromInt(ctx.builder.metadata_items.items(.data)[rhs_index]);
13471 return rhs_data == lhs_key;
13472 }
13473 };
13474
13475 const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
13476 constant,
13477 Adapter{ .builder = self },
13478 );
13479
13480 if (!gop.found_existing) {
13481 gop.key_ptr.* = {};
13482 gop.value_ptr.* = {};
13483 self.metadata_items.appendAssumeCapacity(.{
13484 .tag = .constant,
13485 .data = @intFromEnum(constant),
13486 });
13487 }
13488 return @enumFromInt(gop.index);
13489}
13490
12045pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]const u32 {13491pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]const u32 {
12046 const BitcodeWriter = bitcode_writer.BitcodeWriter(&.{ Type, FunctionAttributes });13492 const BitcodeWriter = bitcode_writer.BitcodeWriter(&.{ Type, FunctionAttributes });
12047 var bitcode = BitcodeWriter.init(allocator, &.{13493 var bitcode = BitcodeWriter.init(allocator, &.{
...@@ -12977,6 +14423,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co...@@ -12977,6 +14423,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
12977 return @intCast(switch (value.unwrap()) {14423 return @intCast(switch (value.unwrap()) {
12978 .instruction => |instruction| instruction.valueIndex(adapter.func) + adapter.firstInstr(),14424 .instruction => |instruction| instruction.valueIndex(adapter.func) + adapter.firstInstr(),
12979 .constant => |constant| adapter.constant_adapter.getConstantIndex(constant),14425 .constant => |constant| adapter.constant_adapter.getConstantIndex(constant),
14426 .metadata => unreachable,
12980 });14427 });
12981 }14428 }
1298214429