Zig 0.17.0-dev (Split by item)

Shortcut keys
?
Show these tips
S
Focus search field
Esc
Clear focus & close tips
U
Jump to source code
↑
Move up in search results
↓
Move down in search results
↵
Go to active search result
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 standard library. Private Struct

Formatter

Private Struct
std.zig.llvm.Builder.Metadata.Formatter
const Formatter = struct

Fields

builder: *Builder
need_comma: bool
map: std.array_hash_map.Auto(union(enum) { metadata: Metadata, debug_location: DebugLocation.Location, }, void) = .empty

Structs

Functions

fn format(data: FormatData, w: *Writer) Writer.Error!void
inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype, special: ?FormatFlags) switch(@TypeOf(node))
inline fn fmtLocal(formatter: *Formatter, prefix: []const u8, value: Value, function: Function.Index) Allocator.Error!std.fmt.Alt(FormatData, format)
fn refUnwrapped(formatter: *Formatter, node: Metadata) Allocator.Error!FormatData.Node
inline fn specialized(formatter: *Formatter, distinct: enum

File

zig/llvm/Builder.zig:9581
9581
9582
9583
9584
9585
9586
9587
9588
9589
9590
9591
9592
9593
9594
9595
9596
9597
9598
9599
9600
9601
9602
9603
9604
9605
9606
9607
9608
9609
9610
9611
9612
9613
9614
9615
9616
9617
9618
9619
9620
9621
9622
9623
9624
9625
9626
9627
9628
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639
9640
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660
9661
9662
9663
9664
9665
9666
9667
9668
9669
9670
9671
9672
9673
9674
9675
9676
9677
9678
9679
9680
9681
9682
9683
9684
9685
9686
9687
9688
9689
9690
9691
9692
9693
9694
9695
9696
9697
9698
9699
9700
9701
9702
9703
9704
9705
9706
9707
9708
9709
9710
9711
9712
9713
9714
9715
9716
9717
9718
9719
9720
9721
9722
9723
9724
9725
9726
9727
9728
9729
9730
9731
9732
9733
9734
9735
9736
9737
9738
9739
9740
9741
9742
9743
9744
9745
9746
9747
9748
9749
9750
9751
9752
9753
9754
9755
9756
9757
9758
9759
9760
9761
9762
9763
9764
9765
9766
9767
9768
9769
9770
9771
9772
9773
9774
9775
9776
9777
9778
9779
9780
9781
9782
9783
9784
9785
9786
9787
9788
9789
9790
9791
9792
9793
9794
9795
9796
9797
9798
9799
9800
9801
9802
9803
9804
9805
9806
9807
9808
9809
9810
9811
9812
9813
9814
9815
9816
9817
9818
9819
9820
9821
9822
9823
9824
9825
9826
9827
9828
9829
9830
9831
9832
9833
9834
    const Formatter = struct {
        builder: *Builder,
        need_comma: bool,
        map: std.array_hash_map.Auto(union(enum) {
            metadata: Metadata,
            debug_location: DebugLocation.Location,
        }, void) = .empty,

        const FormatData = struct {
            formatter: *Formatter,
            prefix: []const u8 = "",
            node: Node,
            specialized: ?FormatFlags,

            const Node = union(enum) {
                none,
                @"inline": Metadata,
                index: u32,

                local_value: ValueData,
                local_metadata: ValueData,
                local_inline: Metadata,
                local_index: u32,

                string: Metadata.String,
                bool: bool,
                u32: u32,
                u64: u64,
                di_flags: DIFlags,
                sp_flags: Subprogram.DISPFlags,
                raw: []const u8,

                const ValueData = struct {
                    value: Value,
                    function: Function.Index,
                };
            };
        };
        fn format(data: FormatData, w: *Writer) Writer.Error!void {
            if (data.node == .none) return;

            const is_specialized = data.specialized != null;

            if (data.formatter.need_comma) try w.writeAll(", ");
            defer data.formatter.need_comma = true;
            try w.writeAll(data.prefix);

            const builder = data.formatter.builder;
            switch (data.node) {
                .none => unreachable,
                .@"inline" => |node| {
                    const needed_comma = data.formatter.need_comma;
                    defer data.formatter.need_comma = needed_comma;
                    data.formatter.need_comma = false;

                    const node_item = node.item(builder);
                    switch (node_item.tag) {
                        .expression => {
                            var extra = builder.metadataExtraDataTrail(Expression, node_item.data);
                            const elements = extra.trail.next(extra.data.elements_len, u32, builder);
                            try w.writeAll("!DIExpression(");
                            for (elements) |element| try format(.{
                                .formatter = data.formatter,
                                .node = .{ .u64 = element },
                                .specialized = .{ .percent = true },
                            }, w);
                            try w.writeByte(')');
                        },
                        .constant => try Constant.format(.{
                            .constant = @fromBackingInt(node_item.data),
                            .builder = builder,
                            .flags = data.specialized orelse .{},
                        }, w),
                        else => unreachable,
                    }
                },
                .index => |node| try w.print("!{d}", .{node}),
                inline .local_value, .local_metadata => |node, node_tag| try Value.format(.{
                    .value = node.value,
                    .function = node.function,
                    .builder = builder,
                    .flags = switch (node_tag) {
                        .local_value => data.specialized orelse .{},
                        .local_metadata => .{ .percent = true },
                        else => unreachable,
                    },
                }, w),
                inline .local_inline, .local_index => |node, node_tag| {
                    if (data.specialized) |flags| {
                        if (flags.onlyPercent()) {
                            try w.print("{f} ", .{Type.metadata.fmt(builder, .percent)});
                        }
                    }
                    try format(.{
                        .formatter = data.formatter,
                        .node = @unionInit(FormatData.Node, @tagName(node_tag)["local_".len..], node),
                        .specialized = .{ .percent = true },
                    }, w);
                },
                .string => |s| {
                    if (is_specialized) try w.writeByte('!');
                    try w.print("{f}", .{s.fmt(builder)});
                },
                inline .bool, .u32, .u64 => |node| try w.print("{}", .{node}),
                inline .di_flags, .sp_flags => |node| try w.print("{f}", .{node}),
                .raw => |node| try w.writeAll(node),
            }
        }
        inline fn fmt(formatter: *Formatter, prefix: []const u8, node: anytype, special: ?FormatFlags) switch (@TypeOf(node)) {
            Metadata, Metadata.Optional, ?Metadata => Allocator.Error,
            else => error{},
        }!std.fmt.Alt(FormatData, format) {
            const Node = @TypeOf(node);
            const MaybeNode = switch (Node) {
                Metadata.Optional => ?Metadata,
                Metadata.String.Optional => ?Metadata.String,
                else => switch (@typeInfo(Node)) {
                    .optional => Node,
                    .null => ?noreturn,
                    else => ?Node,
                },
            };
            const Some = @typeInfo(MaybeNode).optional.child;
            return .{ .data = .{
                .formatter = formatter,
                .prefix = prefix,
                .node = if (@as(MaybeNode, switch (Node) {
                    Metadata.Optional, Metadata.String.Optional => node.unwrap(),
                    else => node,
                })) |some| switch (@typeInfo(Some)) {
                    .@"enum" => |enum_info| switch (Some) {
                        Metadata.String => .{ .string = some },
                        else => if (enum_info.mode == .exhaustive)
                            .{ .raw = @tagName(some) }
                        else
                            @compileError("unknown type to format: " ++ @typeName(Node)),
                    },
                    .enum_literal => .{ .raw = @tagName(some) },
                    .bool => .{ .bool = some },
                    .@"struct" => switch (Some) {
                        DIFlags => .{ .di_flags = some },
                        Metadata => switch (some.kind) {
                            .string => .{ .string = some.toString() },
                            .node, .forward => try formatter.refUnwrapped(some.unwrap(formatter.builder)),
                            .local => unreachable,
                        },
                        Subprogram.DISPFlags => .{ .sp_flags = some },
                        else => @compileError("unknown type to format: " ++ @typeName(Node)),
                    },
                    .int, .comptime_int => .{ .u64 = some },
                    .pointer => .{ .raw = some },
                    else => @compileError("unknown type to format: " ++ @typeName(Node)),
                } else switch (Node) {
                    Metadata.Optional, Metadata.String.Optional => .none,
                    else => switch (@typeInfo(Node)) {
                        .optional, .null => .none,
                        else => unreachable,
                    },
                },
                .specialized = special,
            } };
        }
        inline fn fmtLocal(
            formatter: *Formatter,
            prefix: []const u8,
            value: Value,
            function: Function.Index,
        ) Allocator.Error!std.fmt.Alt(FormatData, format) {
            return .{ .data = .{
                .formatter = formatter,
                .prefix = prefix,
                .node = node: switch (value.unwrap()) {
                    .instruction, .constant => .{ .local_value = .{
                        .value = value,
                        .function = function,
                    } },
                    .metadata => |metadata| if (value == .none) .none else {
                        const unwrapped = metadata.unwrap(formatter.builder);
                        break :node switch (unwrapped.kind) {
                            .string, .node => switch (try formatter.refUnwrapped(unwrapped)) {
                                .@"inline" => |node| .{ .local_inline = node },
                                .index => |node| .{ .local_index = node },
                                else => unreachable,
                            },
                            .forward => unreachable,
                            .local => .{ .local_metadata = .{
                                .value = function.ptrConst(formatter.builder).debug_values[
                                    unwrapped.index
                                ].toValue(),
                                .function = function,
                            } },
                        };
                    },
                },
                .specialized = null,
            } };
        }
        fn refUnwrapped(formatter: *Formatter, node: Metadata) Allocator.Error!FormatData.Node {
            const builder = formatter.builder;
            const unwrapped_metadata = node.unwrap(builder);
            switch (unwrapped_metadata.tag(builder)) {
                .expression, .constant => return .{ .@"inline" = unwrapped_metadata },
                else => |metadata_tag| {
                    assert(!metadata_tag.isInline());
                    const gop = try formatter.map.getOrPut(builder.gpa, .{ .metadata = unwrapped_metadata });
                    return .{ .index = @intCast(gop.index) };
                },
            }
        }

        inline fn specialized(
            formatter: *Formatter,
            distinct: enum { @"!", @"distinct !" },
            node: enum {
                DIFile,
                DICompileUnit,
                DISubprogram,
                DILexicalBlock,
                DILocation,
                DIBasicType,
                DICompositeType,
                DIDerivedType,
                DISubroutineType,
                DIEnumerator,
                DISubrange,
                DILocalVariable,
                DIGlobalVariable,
                DIGlobalVariableExpression,
            },
            nodes: anytype,
            w: *Writer,
        ) !void {
            const names = @typeInfo(@TypeOf(nodes)).@"struct".field_names;

            comptime var fmt_str: []const u8 = "{[distinct]s}{[node]s}(";
            inline for (names) |name| fmt_str = fmt_str ++ "{[" ++ name ++ "]f}";
            fmt_str = fmt_str ++ ")\n";

            const field_names = @as([]const []const u8, &.{ "distinct", "node" }) ++ names;
            comptime var field_types: [2 + names.len]type = undefined;
            @memset(field_types[0..2], []const u8);
            @memset(field_types[2..], std.fmt.Alt(FormatData, format));

            var fmt_args: @Struct(.auto, null, field_names, &field_types, &@splat(.{})) = undefined;
            fmt_args.distinct = @tagName(distinct);
            fmt_args.node = @tagName(node);
            inline for (names) |name| @field(fmt_args, name) = try formatter.fmt(
                name ++ ": ",
                @field(nodes, name),
                null,
            );
            try w.print(fmt_str, fmt_args);
        }
    }