Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

resolveAddressesDwarf

Coverage.resolveAddressesDwarf
pub fn resolveAddressesDwarf(
    cov: *Coverage,
    gpa: Allocator,
    io: Io,
    endian: std.builtin.Endian,
    /// Asserts the addresses are in ascending order.
    sorted_pc_addrs: []const u64,
    /// Asserts its length equals length of `sorted_pc_addrs`.
    output: []SourceLocation,
    d: *Dwarf,
) ResolveAddressesDwarfError!void

File

lib/std/debug/Coverage.zig:146

Code

pub fn resolveAddressesDwarf(
    cov: *Coverage,
    gpa: Allocator,
    io: Io,
    endian: std.builtin.Endian,
    /// Asserts the addresses are in ascending order.
    sorted_pc_addrs: []const u64,
    /// Asserts its length equals length of `sorted_pc_addrs`.
    output: []SourceLocation,
    d: *Dwarf,
) ResolveAddressesDwarfError!void {
    assert(sorted_pc_addrs.len == output.len);
    assert(d.ranges.items.len != 0); // call `populateRanges` first.

    var range_i: usize = 0;
    var range: *std.debug.Dwarf.Range = &d.ranges.items[0];
    var line_table_i: usize = undefined;
    var prev_pc: u64 = 0;
    var prev_cu: ?*std.debug.Dwarf.CompileUnit = null;
    // Protects directories and files tables from other threads.
    try cov.mutex.lock(io);
    defer cov.mutex.unlock(io);
    next_pc: for (sorted_pc_addrs, output) |pc, *out| {
        assert(pc >= prev_pc);
        prev_pc = pc;

        while (pc >= range.end) {
            range_i += 1;
            if (range_i >= d.ranges.items.len) {
                out.* = SourceLocation.invalid;
                continue :next_pc;
            }
            range = &d.ranges.items[range_i];
        }
        if (pc < range.start) {
            out.* = SourceLocation.invalid;
            continue :next_pc;
        }
        const cu = &d.compile_unit_list.items[range.compile_unit_index];
        if (cu != prev_cu) {
            prev_cu = cu;
            if (cu.src_loc_cache == null) {
                cov.mutex.unlock(io);
                defer cov.mutex.lockUncancelable(io);
                d.populateSrcLocCache(gpa, endian, cu) catch |err| switch (err) {
                    error.MissingDebugInfo, error.InvalidDebugInfo => {
                        out.* = SourceLocation.invalid;
                        continue :next_pc;
                    },
                    else => |e| return e,
                };
            }
            const slc = &cu.src_loc_cache.?;
            const table_addrs = slc.line_table.keys();
            line_table_i = std.sort.upperBound(u64, table_addrs, pc, struct {
                fn order(context: u64, item: u64) std.math.Order {
                    return std.math.order(context, item);
                }
            }.order);
        }
        const slc = &cu.src_loc_cache.?;
        const table_addrs = slc.line_table.keys();
        while (line_table_i < table_addrs.len and table_addrs[line_table_i] <= pc) line_table_i += 1;

        const entry = slc.line_table.values()[line_table_i - 1];
        const corrected_file_index = entry.file - @intFromBool(slc.version < 5);
        const file_entry = slc.files[corrected_file_index];
        const dir_path = slc.directories[file_entry.dir_index].path;
        try cov.string_bytes.ensureUnusedCapacity(gpa, dir_path.len + file_entry.path.len + 2);
        const dir_gop = try cov.directories.getOrPutContextAdapted(gpa, dir_path, String.SliceAdapter{
            .string_bytes = cov.string_bytes.items,
        }, String.MapContext{
            .string_bytes = cov.string_bytes.items,
        });
        if (!dir_gop.found_existing)
            dir_gop.key_ptr.* = addStringAssumeCapacity(cov, dir_path);
        const file_gop = try cov.files.getOrPutContextAdapted(gpa, File.SliceAdapter.Entry{
            .directory_index = @intCast(dir_gop.index),
            .basename = file_entry.path,
        }, File.SliceAdapter{
            .string_bytes = cov.string_bytes.items,
        }, File.MapContext{
            .string_bytes = cov.string_bytes.items,
        });
        if (!file_gop.found_existing) file_gop.key_ptr.* = .{
            .directory_index = @intCast(dir_gop.index),
            .basename = addStringAssumeCapacity(cov, file_entry.path),
        };
        out.* = .{
            .file = @fromBackingInt(@intCast(file_gop.index)),
            .line = entry.line,
            .column = entry.column,
        };
    }
}