diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2024-02-22 18:33:36 +0100 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2024-02-22 19:10:52 +0100 |
| commit | 69a6f31596647fa0fca12346edb69dbe5bbc703a (patch) | |
| tree | e01337b2dd4dbe7e7fc95898ba595d51cbc613a6 /src/codegen | |
| parent | 6cc51d3c3311a5d37401ec141424b30f57f62693 (diff) | |
| download | zig-69a6f31596647fa0fca12346edb69dbe5bbc703a.tar.gz zig-69a6f31596647fa0fca12346edb69dbe5bbc703a.zip | |
Builder: fix llvm ir value names
Hello world now verifies when not stripped.
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/llvm.zig | 159 | ||||
| -rw-r--r-- | src/codegen/llvm/Builder.zig | 255 |
2 files changed, 227 insertions, 187 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 26ab6960bd..68c09d48ac 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -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_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_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 }, + ); - 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,28 +1148,27 @@ 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_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_globals_fwd_ref, + try self.builder.debugTuple(self.debug_globals.items), + ); + } if (options.pre_ir_path) |path| { if (std.mem.eql(u8, path, "-")) { @@ -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"); diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index f9ecbdf7b9..f73281d93c 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -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, |
