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.

transArrayAccess

Translator.transArrayAccess
fn transArrayAccess(t: *Translator, scope: *Scope, array_access: Node.ArrayAccess, opt_base: ?ZigNode) TransError!ZigNode

File

lib/compiler/translate-c/Translator.zig:3249

Code

fn transArrayAccess(t: *Translator, scope: *Scope, array_access: Node.ArrayAccess, opt_base: ?ZigNode) TransError!ZigNode {
    // Unwrap the base statement if it's an array decayed to a bare pointer type
    // so that we index the array itself
    const base = base: {
        const base = array_access.base.get(t.tree);
        if (base != .cast) break :base array_access.base;
        if (base.cast.kind != .array_to_pointer) break :base array_access.base;
        break :base base.cast.operand;
    };

    const base_node = opt_base orelse try t.transExpr(scope, base, .used);
    const index = index: {
        const index = try t.transExpr(scope, array_access.index, .used);
        const index_qt = array_access.index.qt(t.tree);
        const maybe_bigger_than_usize = type: switch (index_qt.base(t.comp).type) {
            .bool => {
                break :index try ZigTag.int_from_bool.create(t.arena, index);
            },
            .int => |int| switch (int) {
                .long_long, .ulong_long, .int128, .uint128 => true,
                else => false,
            },
            .bit_int => |bit_int| bit_int.bits > t.comp.target.ptrBitWidth(),
            .@"enum" => |e| if (e.tag) |tag| continue :type tag.base(t.comp).type else false,
            else => unreachable,
        };

        const is_nonnegative_int_literal = if (t.tree.value_map.get(array_access.index)) |val|
            val.compare(.gte, .zero, t.comp)
        else
            false;
        const is_signed = t.signedness(index_qt) == .signed;

        if (is_signed and !is_nonnegative_int_literal) {
            // First cast to `isize` to get proper sign extension and
            // then @bitCast to `usize` to satisfy the compiler.
            const index_isize = try ZigTag.as.create(t.arena, .{
                .lhs = try ZigTag.type.create(t.arena, "isize"),
                .rhs = try ZigTag.int_cast.create(t.arena, index),
            });
            break :index try ZigTag.bit_cast.create(t.arena, index_isize);
        }

        if (maybe_bigger_than_usize) {
            break :index try ZigTag.int_cast.create(t.arena, index);
        }
        break :index index;
    };

    return ZigTag.array_access.create(t.arena, .{
        .lhs = base_node,
        .rhs = index,
    });
}