Builder: fix llvm ir value names

Hello world now verifies when not stripped.
This commit is contained in:
Jacob Young 2024-02-22 18:33:36 +01:00
parent 6cc51d3c33
commit 69a6f31596
3 changed files with 229 additions and 188 deletions

View File

@ -464,7 +464,8 @@ pub fn fieldNames(comptime T: type) *const [fields(T).len][:0]const u8 {
return comptime blk: {
const fieldInfos = fields(T);
var names: [fieldInfos.len][:0]const u8 = undefined;
for (&names, fieldInfos) |*name, field| name.* = field.name;
// This concat can be removed with the next zig1 update.
for (&names, fieldInfos) |*name, field| name.* = field.name ++ "";
break :blk &names;
};
}

View File

@ -849,51 +849,53 @@ pub const Object = struct {
builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }});
// We fully resolve all paths at this point to avoid lack of
// source line info in stack traces or lack of debugging
// information which, if relative paths were used, would be
// very location dependent.
// TODO: the only concern I have with this is WASI as either host or target, should
// we leave the paths as relative then?
// TODO: This is totally wrong. In dwarf, paths are encoded as relative to
// a particular directory, and then the directory path is specified elsewhere.
// In the compiler frontend we have it stored correctly in this
// way already, but here we throw all that sweet information
// into the garbage can by converting into absolute paths. What
// a terrible tragedy.
const compile_unit_dir = blk: {
if (comp.module) |zcu| m: {
const d = try zcu.root_mod.root.joinString(arena, "");
if (d.len == 0) break :m;
if (std.fs.path.isAbsolute(d)) break :blk d;
break :blk std.fs.realpathAlloc(arena, d) catch break :blk d;
}
break :blk try std.process.getCwdAlloc(arena);
};
const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref =
if (!builder.strip)
debug_info: {
// We fully resolve all paths at this point to avoid lack of
// source line info in stack traces or lack of debugging
// information which, if relative paths were used, would be
// very location dependent.
// TODO: the only concern I have with this is WASI as either host or target, should
// we leave the paths as relative then?
// TODO: This is totally wrong. In dwarf, paths are encoded as relative to
// a particular directory, and then the directory path is specified elsewhere.
// In the compiler frontend we have it stored correctly in this
// way already, but here we throw all that sweet information
// into the garbage can by converting into absolute paths. What
// a terrible tragedy.
const compile_unit_dir = blk: {
if (comp.module) |zcu| m: {
const d = try zcu.root_mod.root.joinString(arena, "");
if (d.len == 0) break :m;
if (std.fs.path.isAbsolute(d)) break :blk d;
break :blk std.fs.realpathAlloc(arena, d) catch break :blk d;
}
break :blk try std.process.getCwdAlloc(arena);
};
const debug_file = try builder.debugFile(
try builder.metadataString(comp.root_name),
try builder.metadataString(compile_unit_dir),
);
const debug_file = try builder.debugFile(
try builder.metadataString(comp.root_name),
try builder.metadataString(compile_unit_dir),
);
const debug_enums_fwd_ref = try builder.debugForwardReference();
const debug_globals_fwd_ref = try builder.debugForwardReference();
const debug_enums_fwd_ref = try builder.debugForwardReference();
const debug_globals_fwd_ref = try builder.debugForwardReference();
const debug_compile_unit = try builder.debugCompileUnit(
debug_file,
// Don't use the version string here; LLVM misparses it when it
// includes the git revision.
try builder.metadataStringFmt("zig {d}.{d}.{d}", .{
build_options.semver.major,
build_options.semver.minor,
build_options.semver.patch,
}),
debug_enums_fwd_ref,
debug_globals_fwd_ref,
.{ .optimized = comp.root_mod.optimize_mode != .Debug },
);
const debug_compile_unit = try builder.debugCompileUnit(
debug_file,
// Don't use the version string here; LLVM misparses it when it
// includes the git revision.
try builder.metadataStringFmt("zig {d}.{d}.{d}", .{
build_options.semver.major,
build_options.semver.minor,
build_options.semver.patch,
}),
debug_enums_fwd_ref,
debug_globals_fwd_ref,
.{ .optimized = comp.root_mod.optimize_mode != .Debug },
);
if (!builder.strip) {
const debug_info_version = try builder.debugModuleFlag(
try builder.debugConstant(try builder.intConst(.i32, 2)),
try builder.metadataString("Debug Info Version"),
@ -901,6 +903,7 @@ pub const Object = struct {
);
switch (comp.config.debug_format) {
.strip => unreachable,
.dwarf => |f| {
const dwarf_version = try builder.debugModuleFlag(
try builder.debugConstant(try builder.intConst(.i32, 2)),
@ -939,11 +942,11 @@ pub const Object = struct {
code_view,
});
},
.strip => unreachable,
}
try builder.debugNamed(try builder.metadataString("llvm.dbg.cu"), &.{debug_compile_unit});
}
break :debug_info .{ debug_compile_unit, debug_enums_fwd_ref, debug_globals_fwd_ref };
} else .{.none} ** 3;
const obj = try arena.create(Object);
obj.* = .{
@ -1004,8 +1007,8 @@ pub const Object = struct {
llvm_errors[0] = try o.builder.undefConst(llvm_slice_ty);
for (llvm_errors[1..], error_name_list[1..]) |*llvm_error, name| {
const name_string = try o.builder.string(mod.intern_pool.stringToSlice(name));
const name_init = try o.builder.stringNullConst(name_string);
const name_string = try o.builder.stringNull(mod.intern_pool.stringToSlice(name));
const name_init = try o.builder.stringConst(name_string);
const name_variable_index =
try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
try name_variable_index.setInitializer(name_init, &o.builder);
@ -1016,7 +1019,7 @@ pub const Object = struct {
llvm_error.* = try o.builder.structConst(llvm_slice_ty, &.{
name_variable_index.toConst(&o.builder),
try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len),
try o.builder.intConst(llvm_usize_ty, name_string.slice(&o.builder).?.len - 1),
});
}
@ -1145,29 +1148,28 @@ pub const Object = struct {
try self.genCmpLtErrorsLenFunction();
try self.genModuleLevelAssembly();
{
var i: usize = 0;
while (i < self.debug_unresolved_namespace_scopes.count()) : (i += 1) {
const namespace_index = self.debug_unresolved_namespace_scopes.keys()[i];
const fwd_ref = self.debug_unresolved_namespace_scopes.values()[i];
if (!self.builder.strip) {
for (
self.debug_unresolved_namespace_scopes.keys(),
self.debug_unresolved_namespace_scopes.values(),
) |namespace_index, fwd_ref| {
const namespace = self.module.namespacePtr(namespace_index);
const debug_type = try self.lowerDebugType(namespace.ty);
self.builder.debugForwardReferenceSetType(fwd_ref, debug_type);
}
self.builder.debugForwardReferenceSetType(
self.debug_enums_fwd_ref,
try self.builder.debugTuple(self.debug_enums.items),
);
self.builder.debugForwardReferenceSetType(
self.debug_globals_fwd_ref,
try self.builder.debugTuple(self.debug_globals.items),
);
}
self.builder.debugForwardReferenceSetType(
self.debug_enums_fwd_ref,
try self.builder.debugTuple(self.debug_enums.items),
);
self.builder.debugForwardReferenceSetType(
self.debug_globals_fwd_ref,
try self.builder.debugTuple(self.debug_globals.items),
);
if (options.pre_ir_path) |path| {
if (std.mem.eql(u8, path, "-")) {
self.builder.dump();
@ -1241,13 +1243,12 @@ pub const Object = struct {
};
bitcode_arena_allocator.deinit();
var error_message: [*:0]const u8 = undefined;
const target_triple_sentinel =
try self.gpa.dupeZ(u8, self.builder.target_triple.slice(&self.builder).?);
defer self.gpa.free(target_triple_sentinel);
var target: *llvm.Target = undefined;
if (llvm.Target.getFromTriple(
self.builder.target_triple.slice(&self.builder).?,
&target,
&error_message,
).toBool()) {
var error_message: [*:0]const u8 = undefined;
if (llvm.Target.getFromTriple(target_triple_sentinel, &target, &error_message).toBool()) {
defer llvm.disposeMessage(error_message);
log.err("LLVM failed to parse '{s}': {s}", .{
@ -1286,7 +1287,7 @@ pub const Object = struct {
var target_machine = llvm.TargetMachine.create(
target,
self.builder.target_triple.slice(&self.builder).?,
target_triple_sentinel,
if (self.module.comp.root_mod.resolved_target.result.cpu.model.llvm_name) |s| s.ptr else null,
self.module.comp.root_mod.resolved_target.llvm_cpu_features.?,
opt_level,
@ -1640,15 +1641,15 @@ pub const Object = struct {
function_index.setAttributes(try attributes.finish(&o.builder), &o.builder);
const file = try o.getDebugFile(namespace.file_scope);
const file, const subprogram = if (!o.builder.strip) debug_info: {
const file = try o.getDebugFile(namespace.file_scope);
const subprogram = blk: {
const line_number = decl.src_line + 1;
const is_internal_linkage = decl.val.getExternFunc(zcu) == null and
!zcu.decl_exports.contains(decl_index);
const debug_decl_type = try o.lowerDebugType(decl.ty);
break :blk try o.builder.debugSubprogram(
const subprogram = try o.builder.debugSubprogram(
file,
try o.builder.metadataString(ip.stringToSlice(decl.name)),
try o.builder.metadataStringFromString(function_index.name(&o.builder)),
@ -1668,8 +1669,9 @@ pub const Object = struct {
},
o.debug_compile_unit,
);
};
function_index.setSubprogram(subprogram, &o.builder);
function_index.setSubprogram(subprogram, &o.builder);
break :debug_info .{ file, subprogram };
} else .{.none} ** 2;
var fg: FuncGen = .{
.gpa = gpa,
@ -1924,7 +1926,8 @@ pub const Object = struct {
o: *Object,
ty: Type,
) Allocator.Error!Builder.Metadata {
if (o.builder.strip) return .none;
assert(!o.builder.strip);
const gpa = o.gpa;
const target = o.target;
const mod = o.module;
@ -4608,8 +4611,8 @@ pub const Object = struct {
defer wip_switch.finish(&wip);
for (0..enum_type.names.len) |field_index| {
const name = try o.builder.string(ip.stringToSlice(enum_type.names.get(ip)[field_index]));
const name_init = try o.builder.stringNullConst(name);
const name = try o.builder.stringNull(ip.stringToSlice(enum_type.names.get(ip)[field_index]));
const name_init = try o.builder.stringConst(name);
const name_variable_index =
try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default);
try name_variable_index.setInitializer(name_init, &o.builder);
@ -4620,7 +4623,7 @@ pub const Object = struct {
const name_val = try o.builder.structValue(ret_ty, &.{
name_variable_index.toConst(&o.builder),
try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len),
try o.builder.intConst(usize_ty, name.slice(&o.builder).?.len - 1),
});
const return_block = try wip.block(1, "Name");

View File

@ -77,11 +77,11 @@ pub const String = enum(u32) {
return self.toIndex() == null;
}
pub fn slice(self: String, builder: *const Builder) ?[:0]const u8 {
pub fn slice(self: String, builder: *const Builder) ?[]const u8 {
const index = self.toIndex() orelse return null;
const start = builder.string_indices.items[index];
const end = builder.string_indices.items[index + 1];
return builder.string_bytes.items[start .. end - 1 :0];
return builder.string_bytes.items[start..end];
}
const FormatData = struct {
@ -94,17 +94,21 @@ pub const String = enum(u32) {
_: std.fmt.FormatOptions,
writer: anytype,
) @TypeOf(writer).Error!void {
if (comptime std.mem.indexOfNone(u8, fmt_str, "@\"")) |_|
if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|
@compileError("invalid format string: '" ++ fmt_str ++ "'");
assert(data.string != .none);
const sentinel_slice = data.string.slice(data.builder) orelse
const string_slice = data.string.slice(data.builder) orelse
return writer.print("{d}", .{@intFromEnum(data.string)});
try printEscapedString(sentinel_slice[0 .. sentinel_slice.len + comptime @intFromBool(
std.mem.indexOfScalar(u8, fmt_str, '@') != null,
)], if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|
.always_quote
else
.quote_unless_valid_identifier, writer);
if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_|
return writer.writeAll(string_slice);
try printEscapedString(
string_slice,
if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|
.always_quote
else
.quote_unless_valid_identifier,
writer,
);
}
pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) {
return .{ .data = .{ .string = self, .builder = builder } };
@ -4597,13 +4601,6 @@ pub const Function = struct {
) std.fmt.Formatter(format) {
return .{ .data = .{ .instruction = self, .function = function, .builder = builder } };
}
fn llvmName(self: Instruction.Index, wip: *const WipFunction) [:0]const u8 {
return if (wip.builder.strip)
""
else
wip.names.items[@intFromEnum(self)].slice(wip.builder).?;
}
};
pub const ExtraIndex = u32;
@ -5931,15 +5928,47 @@ pub const WipFunction = struct {
var wip_name: struct {
next_name: String = @enumFromInt(0),
next_unique_name: std.AutoHashMap(String, String),
builder: *Builder,
fn map(wip_name: *@This(), old_name: String) String {
if (old_name != .empty) return old_name;
fn map(wip_name: *@This(), name: String, sep: []const u8) Allocator.Error!String {
switch (name) {
.none => return .none,
.empty => {
assert(wip_name.next_name != .none);
defer wip_name.next_name = @enumFromInt(@intFromEnum(wip_name.next_name) + 1);
return wip_name.next_name;
},
_ => {
assert(!name.isAnon());
const gop = try wip_name.next_unique_name.getOrPut(name);
if (!gop.found_existing) {
gop.value_ptr.* = @enumFromInt(0);
return name;
}
const new_name = wip_name.next_name;
wip_name.next_name = @enumFromInt(@intFromEnum(new_name) + 1);
return new_name;
while (true) {
gop.value_ptr.* = @enumFromInt(@intFromEnum(gop.value_ptr.*) + 1);
const unique_name = try wip_name.builder.fmt("{r}{s}{r}", .{
name.fmt(wip_name.builder),
sep,
gop.value_ptr.fmt(wip_name.builder),
});
const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name);
if (!unique_gop.found_existing) {
unique_gop.value_ptr.* = @enumFromInt(0);
return unique_name;
}
}
},
}
}
} = .{};
} = .{
.next_unique_name = std.AutoHashMap(String, String).init(gpa),
.builder = self.builder,
};
defer wip_name.next_unique_name.deinit();
var value_index: u32 = 0;
for (0..params_len) |param_index| {
const old_argument_index: Instruction.Index = @enumFromInt(param_index);
@ -5950,8 +5979,9 @@ pub const WipFunction = struct {
value_indices[function.instructions.len] = value_index;
value_index += 1;
function.instructions.appendAssumeCapacity(argument);
names[@intFromEnum(new_argument_index)] = wip_name.map(
names[@intFromEnum(new_argument_index)] = try wip_name.map(
if (self.builder.strip) .empty else self.names.items[@intFromEnum(old_argument_index)],
".",
);
if (self.debug_locations.get(old_argument_index)) |location| {
debug_locations.putAssumeCapacity(new_argument_index, location);
@ -5967,7 +5997,7 @@ pub const WipFunction = struct {
.tag = .block,
.data = current_block.incoming,
});
names[@intFromEnum(new_block_index)] = wip_name.map(current_block.name);
names[@intFromEnum(new_block_index)] = try wip_name.map(current_block.name, "");
for (current_block.instructions.items) |old_instruction_index| {
const new_instruction_index: Instruction.Index =
@enumFromInt(function.instructions.len);
@ -6268,10 +6298,10 @@ pub const WipFunction = struct {
},
}
function.instructions.appendAssumeCapacity(instruction);
names[@intFromEnum(new_instruction_index)] = wip_name.map(if (self.builder.strip)
names[@intFromEnum(new_instruction_index)] = try wip_name.map(if (self.builder.strip)
if (old_instruction_index.hasResultWip(self)) .empty else .none
else
self.names.items[@intFromEnum(old_instruction_index)]);
self.names.items[@intFromEnum(old_instruction_index)], ".");
if (self.debug_locations.get(old_instruction_index)) |location| {
debug_locations.putAssumeCapacity(new_instruction_index, location);
@ -6687,7 +6717,6 @@ pub const Constant = enum(u32) {
packed_structure,
array,
string,
string_null,
vector,
splat,
zeroinitializer,
@ -6943,10 +6972,8 @@ pub const Constant = enum(u32) {
=> builder.constantExtraData(Aggregate, item.data).type,
.splat => builder.constantExtraData(Splat, item.data).type,
.string,
.string_null,
=> builder.arrayTypeAssumeCapacity(
@as(String, @enumFromInt(item.data)).slice(builder).?.len +
@intFromBool(item.tag == .string_null),
@as(String, @enumFromInt(item.data)).slice(builder).?.len,
.i8,
),
.blockaddress => builder.ptrTypeAssumeCapacity(
@ -7281,13 +7308,9 @@ pub const Constant = enum(u32) {
}
try writer.writeByte('>');
},
inline .string,
.string_null,
=> |tag| try writer.print("c{\"" ++ switch (tag) {
.string => "",
.string_null => "@",
else => unreachable,
} ++ "}", .{@as(String, @enumFromInt(item.data)).fmt(data.builder)}),
.string => try writer.print("c{\"}", .{
@as(String, @enumFromInt(item.data)).fmt(data.builder),
}),
.blockaddress => |tag| {
const extra = data.builder.constantExtraData(BlockAddress, item.data);
const function = extra.function.ptrConst(data.builder);
@ -7658,7 +7681,7 @@ pub const Metadata = enum(u32) {
{
const index = @intFromEnum(metadata) - Metadata.first_forward_reference;
metadata = builder.metadata_forward_references.items[index];
std.debug.assert(metadata != .none);
assert(metadata != .none);
}
return metadata;
}
@ -8058,30 +8081,33 @@ pub const Metadata = enum(u32) {
}
},
.index => |item| try writer.print("!{d}", .{item}),
.value => |item| try Value.format(.{
.value = switch (item.value.unwrap()) {
.instruction, .constant => item.value,
.metadata => |metadata| if (@intFromEnum(metadata) >=
Metadata.first_local_metadata)
item.function.ptrConst(builder).debug_values[
.value => |item| switch (item.value.unwrap()) {
.instruction, .constant => try Value.format(.{
.value = item.value,
.function = item.function,
.builder = builder,
}, fmt_str, fmt_opts, writer),
.metadata => |metadata| if (@intFromEnum(metadata) >=
Metadata.first_local_metadata)
try Value.format(.{
.value = item.function.ptrConst(builder).debug_values[
@intFromEnum(metadata) - Metadata.first_local_metadata
].toValue()
else if (metadata != .none) {
if (comptime std.mem.eql(u8, fmt_str, "%"))
try writer.print("{%} ", .{Type.metadata.fmt(builder)});
try Metadata.Formatter.format(.{
.formatter = data.formatter,
.item = data.formatter.unwrapAssumeExists(metadata),
}, "", fmt_opts, writer);
return;
} else return,
].toValue(),
.function = item.function,
.builder = builder,
}, "%", fmt_opts, writer)
else if (metadata != .none) {
if (comptime std.mem.eql(u8, fmt_str, "%"))
try writer.print("{%} ", .{Type.metadata.fmt(builder)});
try Metadata.Formatter.format(.{
.formatter = data.formatter,
.item = data.formatter.unwrapAssumeExists(metadata),
}, "", fmt_opts, writer);
},
.function = item.function,
.builder = builder,
}, "%", fmt_opts, writer),
},
.string => |item| try writer.print("{}", .{item.fmt(data.formatter.builder)}),
inline .bool, .u32, .u64 => |item| try writer.print("{}", .{item}),
.raw => |item| try writer.print("{s}", .{item}),
.raw => |item| try writer.writeAll(item),
}
}
inline fn fmt(formatter: *Formatter, prefix: []const u8, item: anytype) switch (@TypeOf(item)) {
@ -8188,7 +8214,7 @@ pub const Metadata = enum(u32) {
inline for (fields[2..], names) |*field, name| {
fmt_str = fmt_str ++ "{[" ++ name ++ "]}";
field.* = .{
.name = name ++ "",
.name = name,
.type = std.fmt.Formatter(format),
.default_value = null,
.is_comptime = false,
@ -8305,7 +8331,7 @@ pub fn init(options: Options) Allocator.Error!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);
if (!self.strip) assert(try self.debugNone() == .none);
try self.metadata_string_indices.append(self.gpa, 0);
assert(try self.metadataString("") == .none);
@ -8374,19 +8400,22 @@ pub fn finishModuleAsm(self: *Builder) Allocator.Error!void {
}
pub fn string(self: *Builder, bytes: []const u8) Allocator.Error!String {
try self.string_bytes.ensureUnusedCapacity(self.gpa, bytes.len + 1);
try self.string_bytes.ensureUnusedCapacity(self.gpa, bytes.len);
try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
try self.string_map.ensureUnusedCapacity(self.gpa, 1);
const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });
if (!gop.found_existing) {
self.string_bytes.appendSliceAssumeCapacity(bytes);
self.string_bytes.appendAssumeCapacity(0);
self.string_indices.appendAssumeCapacity(@intCast(self.string_bytes.items.len));
}
return String.fromIndex(gop.index);
}
pub fn stringNull(self: *Builder, bytes: [:0]const u8) Allocator.Error!String {
return self.string(bytes[0 .. bytes.len + 1]);
}
pub fn stringIfExists(self: *const Builder, bytes: []const u8) ?String {
return String.fromIndex(
self.string_map.getIndexAdapted(bytes, String.Adapter{ .builder = self }) orelse return null,
@ -8395,15 +8424,15 @@ pub fn stringIfExists(self: *const Builder, bytes: []const u8) ?String {
pub fn fmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allocator.Error!String {
try self.string_map.ensureUnusedCapacity(self.gpa, 1);
try self.string_bytes.ensureUnusedCapacity(self.gpa, @intCast(std.fmt.count(fmt_str ++ .{0}, fmt_args)));
try self.string_bytes.ensureUnusedCapacity(self.gpa, @intCast(std.fmt.count(fmt_str, fmt_args)));
try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
return self.fmtAssumeCapacity(fmt_str, fmt_args);
}
pub fn fmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) String {
const start = self.string_bytes.items.len;
self.string_bytes.writer(self.gpa).print(fmt_str ++ .{0}, fmt_args) catch unreachable;
const bytes: []const u8 = self.string_bytes.items[start .. self.string_bytes.items.len - 1];
self.string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable;
const bytes: []const u8 = self.string_bytes.items[start..];
const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });
if (gop.found_existing) {
@ -8468,7 +8497,7 @@ pub fn structType(
pub fn opaqueType(self: *Builder, name: String) Allocator.Error!Type {
try self.string_map.ensureUnusedCapacity(self.gpa, 1);
if (name.slice(self)) |id| {
const count: usize = comptime std.fmt.count("{d}" ++ .{0}, .{std.math.maxInt(u32)});
const count: usize = comptime std.fmt.count("{d}", .{std.math.maxInt(u32)});
try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count);
}
try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
@ -8911,16 +8940,6 @@ pub fn stringValue(self: *Builder, val: String) Allocator.Error!Value {
return (try self.stringConst(val)).toValue();
}
pub fn stringNullConst(self: *Builder, val: String) Allocator.Error!Constant {
try self.ensureUnusedTypeCapacity(1, Type.Array, 0);
try self.ensureUnusedConstantCapacity(1, NoExtra, 0);
return self.stringNullConstAssumeCapacity(val);
}
pub fn stringNullValue(self: *Builder, val: String) Allocator.Error!Value {
return (try self.stringNullConst(val)).toValue();
}
pub fn vectorConst(self: *Builder, ty: Type, vals: []const Constant) Allocator.Error!Constant {
try self.ensureUnusedConstantCapacity(1, Constant.Aggregate, vals.len);
return self.vectorConstAssumeCapacity(ty, vals);
@ -9354,7 +9373,7 @@ pub fn printUnbuffered(
defer metadata_formatter.need_comma = undefined;
try writer.print("{ }{}", .{
function.alignment,
try metadata_formatter.fmt("!dbg ", global.dbg),
try metadata_formatter.fmt(" !dbg ", global.dbg),
});
}
if (function.instructions.len > 0) {
@ -9513,7 +9532,8 @@ pub fn printUnbuffered(
const name = instruction_index.name(&function);
if (@intFromEnum(instruction_index) > params_len)
try writer.writeByte('\n');
try writer.print("{}:", .{name.fmt(self)});
try writer.print("{}:\n", .{name.fmt(self)});
continue;
},
.br => |tag| {
const target: Function.Block.Index = @enumFromInt(instruction.data);
@ -9965,6 +9985,7 @@ pub fn printUnbuffered(
.composite_union_type,
.composite_enumeration_type,
.composite_array_type,
.composite_vector_type,
=> |kind| {
const extra = self.metadataExtraData(Metadata.CompositeType, metadata_item.data);
try metadata_formatter.specialized(.@"distinct !", .DICompositeType, .{
@ -10165,9 +10186,6 @@ pub fn printUnbuffered(
.expr = extra.expression,
}, writer);
},
else => {
try writer.writeByte('\n');
},
}
}
}
@ -10206,7 +10224,7 @@ fn printEscapedString(
fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void {
try self.string_map.ensureUnusedCapacity(self.gpa, 1);
if (name.slice(self)) |id| {
const count: usize = comptime std.fmt.count("{d}" ++ .{0}, .{std.math.maxInt(u32)});
const count: usize = comptime std.fmt.count("{d}", .{std.math.maxInt(u32)});
try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count);
}
try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
@ -10881,16 +10899,6 @@ fn stringConstAssumeCapacity(self: *Builder, val: String) Constant {
return result.constant;
}
fn stringNullConstAssumeCapacity(self: *Builder, val: String) Constant {
const slice = val.slice(self).?;
const ty = self.arrayTypeAssumeCapacity(slice.len + 1, .i8);
if (std.mem.allEqual(u8, slice, 0)) return self.zeroInitConstAssumeCapacity(ty);
const result = self.getOrPutConstantNoExtraAssumeCapacity(
.{ .tag = .string_null, .data = @intFromEnum(val) },
);
return result.constant;
}
fn vectorConstAssumeCapacity(self: *Builder, ty: Type, vals: []const Constant) Constant {
assert(ty.isVector(self));
assert(ty.vectorLen(self) == vals.len);
@ -11756,8 +11764,8 @@ pub fn metadataStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args:
pub fn metadataStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) MetadataString {
const start = self.metadata_string_bytes.items.len;
self.metadata_string_bytes.writer(self.gpa).print(fmt_str, fmt_args) catch unreachable;
const bytes: []const u8 = self.metadata_string_bytes.items[start..self.metadata_string_bytes.items.len];
self.metadata_string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable;
const bytes: []const u8 = self.metadata_string_bytes.items[start..];
const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self });
if (gop.found_existing) {
@ -12042,7 +12050,7 @@ pub fn debugEnumerator(
bit_width: u32,
value: std.math.big.int.Const,
) Allocator.Error!Metadata {
std.debug.assert(!(unsigned and !value.positive));
assert(!(unsigned and !value.positive));
try self.ensureUnusedMetadataCapacity(1, Metadata.Enumerator, 0);
try self.metadata_limbs.ensureUnusedCapacity(self.gpa, value.limbs.len);
return self.debugEnumeratorAssumeCapacity(name, unsigned, bit_width, value);
@ -12147,7 +12155,7 @@ pub fn debugConstant(self: *Builder, value: Constant) Allocator.Error!Metadata {
}
pub fn debugForwardReferenceSetType(self: *Builder, fwd_ref: Metadata, ty: Metadata) void {
std.debug.assert(
assert(
@intFromEnum(fwd_ref) >= Metadata.first_forward_reference and
@intFromEnum(fwd_ref) <= Metadata.first_local_metadata,
);
@ -12226,7 +12234,8 @@ fn metadataDistinctAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anyt
}
fn debugNamedAssumeCapacity(self: *Builder, name: MetadataString, operands: []const Metadata) void {
std.debug.assert(name != .none);
assert(!self.strip);
assert(name != .none);
const extra_index: u32 = @intCast(self.metadata_extra.items.len);
self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(operands));
@ -12238,6 +12247,7 @@ fn debugNamedAssumeCapacity(self: *Builder, name: MetadataString, operands: []co
}
pub fn debugNoneAssumeCapacity(self: *Builder) Metadata {
assert(!self.strip);
return self.metadataSimpleAssumeCapacity(.none, .{});
}
@ -12246,6 +12256,7 @@ fn debugFileAssumeCapacity(
filename: MetadataString,
directory: MetadataString,
) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.file, Metadata.File{
.filename = filename,
.directory = directory,
@ -12260,6 +12271,7 @@ pub fn debugCompileUnitAssumeCapacity(
globals: Metadata,
options: Metadata.CompileUnit.Options,
) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(
if (options.optimized) .@"compile_unit optimized" else .compile_unit,
Metadata.CompileUnit{
@ -12282,6 +12294,7 @@ fn debugSubprogramAssumeCapacity(
options: Metadata.Subprogram.Options,
compile_unit: Metadata,
) Metadata {
assert(!self.strip);
const tag: Metadata.Tag = @enumFromInt(@intFromEnum(Metadata.Tag.subprogram) +
@as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2)));
return self.metadataDistinctAssumeCapacity(tag, Metadata.Subprogram{
@ -12297,6 +12310,7 @@ fn debugSubprogramAssumeCapacity(
}
fn debugLexicalBlockAssumeCapacity(self: *Builder, scope: Metadata, file: Metadata, line: u32, column: u32) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.lexical_block, Metadata.LexicalBlock{
.scope = scope,
.file = file,
@ -12306,6 +12320,7 @@ fn debugLexicalBlockAssumeCapacity(self: *Builder, scope: Metadata, file: Metada
}
fn debugLocationAssumeCapacity(self: *Builder, line: u32, column: u32, scope: Metadata, inlined_at: Metadata) Metadata {
assert(!self.strip);
return self.metadataSimpleAssumeCapacity(.location, Metadata.Location{
.line = line,
.column = column,
@ -12315,6 +12330,7 @@ fn debugLocationAssumeCapacity(self: *Builder, line: u32, column: u32, scope: Me
}
fn debugBoolTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.basic_bool_type, Metadata.BasicType{
.name = name,
.size_in_bits_lo = @truncate(size_in_bits),
@ -12323,6 +12339,7 @@ fn debugBoolTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bit
}
fn debugUnsignedTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.basic_unsigned_type, Metadata.BasicType{
.name = name,
.size_in_bits_lo = @truncate(size_in_bits),
@ -12331,6 +12348,7 @@ fn debugUnsignedTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in
}
fn debugSignedTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.basic_signed_type, Metadata.BasicType{
.name = name,
.size_in_bits_lo = @truncate(size_in_bits),
@ -12339,6 +12357,7 @@ fn debugSignedTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_b
}
fn debugFloatTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bits: u64) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.basic_float_type, Metadata.BasicType{
.name = name,
.size_in_bits_lo = @truncate(size_in_bits),
@ -12347,6 +12366,7 @@ fn debugFloatTypeAssumeCapacity(self: *Builder, name: MetadataString, size_in_bi
}
fn debugForwardReferenceAssumeCapacity(self: *Builder) Metadata {
assert(!self.strip);
const index = Metadata.first_forward_reference + self.metadata_forward_references.items.len;
self.metadata_forward_references.appendAssumeCapacity(.none);
return @enumFromInt(index);
@ -12363,6 +12383,7 @@ fn debugStructTypeAssumeCapacity(
align_in_bits: u64,
fields_tuple: Metadata,
) Metadata {
assert(!self.strip);
return self.debugCompositeTypeAssumeCapacity(
.composite_struct_type,
name,
@ -12387,6 +12408,7 @@ fn debugUnionTypeAssumeCapacity(
align_in_bits: u64,
fields_tuple: Metadata,
) Metadata {
assert(!self.strip);
return self.debugCompositeTypeAssumeCapacity(
.composite_union_type,
name,
@ -12411,6 +12433,7 @@ fn debugEnumerationTypeAssumeCapacity(
align_in_bits: u64,
fields_tuple: Metadata,
) Metadata {
assert(!self.strip);
return self.debugCompositeTypeAssumeCapacity(
.composite_enumeration_type,
name,
@ -12435,6 +12458,7 @@ fn debugArrayTypeAssumeCapacity(
align_in_bits: u64,
fields_tuple: Metadata,
) Metadata {
assert(!self.strip);
return self.debugCompositeTypeAssumeCapacity(
.composite_array_type,
name,
@ -12459,6 +12483,7 @@ fn debugVectorTypeAssumeCapacity(
align_in_bits: u64,
fields_tuple: Metadata,
) Metadata {
assert(!self.strip);
return self.debugCompositeTypeAssumeCapacity(
.composite_vector_type,
name,
@ -12484,6 +12509,7 @@ fn debugCompositeTypeAssumeCapacity(
align_in_bits: u64,
fields_tuple: Metadata,
) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(tag, Metadata.CompositeType{
.name = name,
.file = file,
@ -12509,6 +12535,7 @@ fn debugPointerTypeAssumeCapacity(
align_in_bits: u64,
offset_in_bits: u64,
) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.derived_pointer_type, Metadata.DerivedType{
.name = name,
.file = file,
@ -12535,6 +12562,7 @@ fn debugMemberTypeAssumeCapacity(
align_in_bits: u64,
offset_in_bits: u64,
) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.derived_member_type, Metadata.DerivedType{
.name = name,
.file = file,
@ -12554,6 +12582,7 @@ fn debugSubroutineTypeAssumeCapacity(
self: *Builder,
types_tuple: Metadata,
) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.subroutine_type, Metadata.SubroutineType{
.types_tuple = types_tuple,
});
@ -12566,6 +12595,7 @@ fn debugEnumeratorAssumeCapacity(
bit_width: u32,
value: std.math.big.int.Const,
) Metadata {
assert(!self.strip);
const Key = struct { tag: Metadata.Tag, index: Metadata };
const Adapter = struct {
pub fn hash(_: @This(), key: Key) u32 {
@ -12587,7 +12617,7 @@ fn debugEnumeratorAssumeCapacity(
else
.enumerator_signed_negative;
std.debug.assert(!(tag == .enumerator_unsigned and !value.positive));
assert(!(tag == .enumerator_unsigned and !value.positive));
const gop = self.metadata_map.getOrPutAssumeCapacityAdapted(
Key{ .tag = tag, .index = @enumFromInt(self.metadata_map.count()) },
@ -12616,6 +12646,7 @@ fn debugSubrangeAssumeCapacity(
lower_bound: Metadata,
count: Metadata,
) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.subrange, Metadata.Subrange{
.lower_bound = lower_bound,
.count = count,
@ -12626,6 +12657,7 @@ fn debugExpressionAssumeCapacity(
self: *Builder,
elements: []const u32,
) Metadata {
assert(!self.strip);
const Key = struct {
elements: []const u32,
};
@ -12672,6 +12704,7 @@ fn debugTupleAssumeCapacity(
self: *Builder,
elements: []const Metadata,
) Metadata {
assert(!self.strip);
const Key = struct {
elements: []const Metadata,
};
@ -12720,6 +12753,7 @@ fn debugModuleFlagAssumeCapacity(
name: MetadataString,
constant: Metadata,
) Metadata {
assert(!self.strip);
return self.metadataSimpleAssumeCapacity(.module_flag, Metadata.ModuleFlag{
.behavior = behavior,
.name = name,
@ -12734,7 +12768,8 @@ fn debugLocalVarAssumeCapacity(
scope: Metadata,
line: u32,
ty: Metadata,
) Allocator.Error!Metadata {
) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.local_var, Metadata.LocalVar{
.name = name,
.file = file,
@ -12752,7 +12787,8 @@ fn debugParameterAssumeCapacity(
line: u32,
ty: Metadata,
arg_no: u32,
) Allocator.Error!Metadata {
) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.parameter, Metadata.Parameter{
.name = name,
.file = file,
@ -12773,7 +12809,8 @@ fn debugGlobalVarAssumeCapacity(
ty: Metadata,
variable: Variable.Index,
options: Metadata.GlobalVar.Options,
) Allocator.Error!Metadata {
) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(
if (options.local) .@"global_var local" else .global_var,
Metadata.GlobalVar{
@ -12793,6 +12830,7 @@ fn debugGlobalVarExpressionAssumeCapacity(
variable: Metadata,
expression: Metadata,
) Metadata {
assert(!self.strip);
return self.metadataDistinctAssumeCapacity(.global_var_expression, Metadata.GlobalVarExpression{
.variable = variable,
.expression = expression,
@ -12800,6 +12838,7 @@ fn debugGlobalVarExpressionAssumeCapacity(
}
fn debugConstantAssumeCapacity(self: *Builder, constant: Constant) Metadata {
assert(!self.strip);
const Adapter = struct {
builder: *const Builder,
pub fn hash(_: @This(), key: Constant) u32 {
@ -13528,18 +13567,16 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
}
},
.string,
.string_null,
=> {
const str: String = @enumFromInt(data);
if (str == .none) {
try constants_block.writeAbbrev(Constants.Null{});
} else {
const slice = str.slice(self) orelse unreachable;
switch (tags[index]) {
.string => try constants_block.writeAbbrev(Constants.String{ .string = slice }),
.string_null => try constants_block.writeAbbrev(Constants.CString{ .string = slice }),
else => unreachable,
}
if (slice.len > 0 and slice[slice.len - 1] == 0)
try constants_block.writeAbbrev(Constants.CString{ .string = slice[0 .. slice.len - 1] })
else
try constants_block.writeAbbrev(Constants.String{ .string = slice });
}
},
.bitcast,
@ -13918,7 +13955,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
},
.location => {
const extra = self.metadataExtraData(Metadata.Location, data);
std.debug.assert(extra.scope != .none);
assert(extra.scope != .none);
try metadata_block.writeAbbrev(MetadataBlock.Location{
.line = extra.line,
.column = extra.column,