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 Function

rvalueInner

Private Function
std.zig.AstGen.rvalueInner
fn rvalueInner(
    gz: *GenZir,
    ri: ResultInfo,
    raw_result: Zir.Inst.Ref,
    src_node: Ast.Node.Index,
    allow_coerce_pre_ref: bool,
) InnerError!Zir.Inst.Ref

Params

Errors

OutOfMemory
AnalysisFail

File

zig/AstGen.zig:10501
10501
10502
10503
10504
10505
10506
10507
10508
10509
10510
10511
10512
10513
10514
10515
10516
10517
10518
10519
10520
10521
10522
10523
10524
10525
10526
10527
10528
10529
10530
10531
10532
10533
10534
10535
10536
10537
10538
10539
10540
10541
10542
10543
10544
10545
10546
10547
10548
10549
10550
10551
10552
10553
10554
10555
10556
10557
10558
10559
10560
10561
10562
10563
10564
10565
10566
10567
10568
10569
10570
10571
10572
10573
10574
10575
10576
10577
10578
10579
10580
10581
10582
10583
10584
10585
10586
10587
10588
10589
10590
10591
10592
10593
10594
10595
10596
10597
10598
10599
10600
10601
10602
10603
10604
10605
10606
10607
10608
10609
10610
10611
10612
10613
10614
10615
10616
10617
10618
10619
10620
10621
10622
10623
10624
10625
10626
10627
10628
10629
10630
10631
10632
10633
10634
10635
10636
10637
10638
10639
10640
10641
10642
10643
10644
10645
10646
10647
10648
10649
10650
10651
10652
10653
10654
10655
10656
10657
10658
10659
10660
10661
10662
10663
10664
10665
10666
10667
10668
10669
10670
10671
10672
10673
10674
10675
10676
10677
10678
10679
10680
10681
10682
10683
10684
10685
10686
10687
10688
10689
10690
10691
10692
10693
10694
10695
10696
10697
10698
10699
10700
10701
10702
10703
10704
10705
10706
10707
10708
10709
10710
fn rvalueInner(
    gz: *GenZir,
    ri: ResultInfo,
    raw_result: Zir.Inst.Ref,
    src_node: Ast.Node.Index,
    allow_coerce_pre_ref: bool,
) InnerError!Zir.Inst.Ref {
    const result = r: {
        if (raw_result.toIndex()) |result_index| {
            const zir_tags = gz.astgen.instructions.items(.tag);
            const data = gz.astgen.instructions.items(.data)[@backingInt(result_index)];
            if (zir_tags[@backingInt(result_index)].isAlwaysVoid(data)) {
                break :r Zir.Inst.Ref.void_value;
            }
        }
        break :r raw_result;
    };
    if (gz.endsWithNoReturn()) return result;
    switch (ri.rl) {
        .none, .coerced_ty => return result,
        .discard => {
            // Emit a compile error for discarding error values.
            _ = try gz.addUnNode(.ensure_result_non_error, result, src_node);
            return .void_value;
        },
        .ref, .ref_const, .ref_coerced_ty => {
            const coerced_result = if (allow_coerce_pre_ref and ri.rl == .ref_coerced_ty) res: {
                const ptr_ty = ri.rl.ref_coerced_ty;
                break :res try gz.addPlNode(.coerce_ptr_elem_ty, src_node, Zir.Inst.Bin{
                    .lhs = ptr_ty,
                    .rhs = result,
                });
            } else result;
            // We need a pointer but we have a value.
            // Unfortunately it's not quite as simple as directly emitting a ref
            // instruction here because we need subsequent address-of operator on
            // const locals to return the same address.
            const astgen = gz.astgen;
            const tree = astgen.tree;
            const src_token = tree.firstToken(src_node);
            const result_index = coerced_result.toIndex() orelse
                return gz.addUnTok(.ref, coerced_result, src_token);
            const gop = try astgen.ref_table.getOrPut(astgen.gpa, result_index);
            if (!gop.found_existing) {
                gop.value_ptr.* = try gz.makeUnTok(.ref, coerced_result, src_token);
            }
            return gop.value_ptr.*.toRef();
        },
        .ty => |ty_inst| {
            // Quickly eliminate some common, unnecessary type coercion.
            const as_ty = @as(u64, @backingInt(Zir.Inst.Ref.type_type)) << 32;
            const as_bool = @as(u64, @backingInt(Zir.Inst.Ref.bool_type)) << 32;
            const as_void = @as(u64, @backingInt(Zir.Inst.Ref.void_type)) << 32;
            const as_comptime_int = @as(u64, @backingInt(Zir.Inst.Ref.comptime_int_type)) << 32;
            const as_usize = @as(u64, @backingInt(Zir.Inst.Ref.usize_type)) << 32;
            const as_u1 = @as(u64, @backingInt(Zir.Inst.Ref.u1_type)) << 32;
            const as_u8 = @as(u64, @backingInt(Zir.Inst.Ref.u8_type)) << 32;
            switch ((@as(u64, @backingInt(ty_inst)) << 32) | @as(u64, @backingInt(result))) {
                as_ty | @backingInt(Zir.Inst.Ref.u1_type),
                as_ty | @backingInt(Zir.Inst.Ref.u8_type),
                as_ty | @backingInt(Zir.Inst.Ref.i8_type),
                as_ty | @backingInt(Zir.Inst.Ref.u16_type),
                as_ty | @backingInt(Zir.Inst.Ref.u29_type),
                as_ty | @backingInt(Zir.Inst.Ref.i16_type),
                as_ty | @backingInt(Zir.Inst.Ref.u32_type),
                as_ty | @backingInt(Zir.Inst.Ref.i32_type),
                as_ty | @backingInt(Zir.Inst.Ref.u64_type),
                as_ty | @backingInt(Zir.Inst.Ref.i64_type),
                as_ty | @backingInt(Zir.Inst.Ref.u128_type),
                as_ty | @backingInt(Zir.Inst.Ref.i128_type),
                as_ty | @backingInt(Zir.Inst.Ref.usize_type),
                as_ty | @backingInt(Zir.Inst.Ref.isize_type),
                as_ty | @backingInt(Zir.Inst.Ref.c_char_type),
                as_ty | @backingInt(Zir.Inst.Ref.c_short_type),
                as_ty | @backingInt(Zir.Inst.Ref.c_ushort_type),
                as_ty | @backingInt(Zir.Inst.Ref.c_int_type),
                as_ty | @backingInt(Zir.Inst.Ref.c_uint_type),
                as_ty | @backingInt(Zir.Inst.Ref.c_long_type),
                as_ty | @backingInt(Zir.Inst.Ref.c_ulong_type),
                as_ty | @backingInt(Zir.Inst.Ref.c_longlong_type),
                as_ty | @backingInt(Zir.Inst.Ref.c_ulonglong_type),
                as_ty | @backingInt(Zir.Inst.Ref.c_longdouble_type),
                as_ty | @backingInt(Zir.Inst.Ref.f16_type),
                as_ty | @backingInt(Zir.Inst.Ref.f32_type),
                as_ty | @backingInt(Zir.Inst.Ref.f64_type),
                as_ty | @backingInt(Zir.Inst.Ref.f80_type),
                as_ty | @backingInt(Zir.Inst.Ref.f128_type),
                as_ty | @backingInt(Zir.Inst.Ref.anyopaque_type),
                as_ty | @backingInt(Zir.Inst.Ref.bool_type),
                as_ty | @backingInt(Zir.Inst.Ref.void_type),
                as_ty | @backingInt(Zir.Inst.Ref.type_type),
                as_ty | @backingInt(Zir.Inst.Ref.anyerror_type),
                as_ty | @backingInt(Zir.Inst.Ref.comptime_int_type),
                as_ty | @backingInt(Zir.Inst.Ref.comptime_float_type),
                as_ty | @backingInt(Zir.Inst.Ref.noreturn_type),
                as_ty | @backingInt(Zir.Inst.Ref.anyframe_type),
                as_ty | @backingInt(Zir.Inst.Ref.null_type),
                as_ty | @backingInt(Zir.Inst.Ref.undefined_type),
                as_ty | @backingInt(Zir.Inst.Ref.enum_literal_type),
                as_ty | @backingInt(Zir.Inst.Ref.ptr_usize_type),
                as_ty | @backingInt(Zir.Inst.Ref.ptr_const_comptime_int_type),
                as_ty | @backingInt(Zir.Inst.Ref.manyptr_u8_type),
                as_ty | @backingInt(Zir.Inst.Ref.manyptr_const_u8_type),
                as_ty | @backingInt(Zir.Inst.Ref.manyptr_const_u8_sentinel_0_type),
                as_ty | @backingInt(Zir.Inst.Ref.slice_const_u8_type),
                as_ty | @backingInt(Zir.Inst.Ref.slice_const_u8_sentinel_0_type),
                as_ty | @backingInt(Zir.Inst.Ref.anyerror_void_error_union_type),
                as_ty | @backingInt(Zir.Inst.Ref.generic_poison_type),
                as_ty | @backingInt(Zir.Inst.Ref.empty_tuple_type),
                as_comptime_int | @backingInt(Zir.Inst.Ref.zero),
                as_comptime_int | @backingInt(Zir.Inst.Ref.one),
                as_comptime_int | @backingInt(Zir.Inst.Ref.negative_one),
                as_usize | @backingInt(Zir.Inst.Ref.undef_usize),
                as_usize | @backingInt(Zir.Inst.Ref.zero_usize),
                as_usize | @backingInt(Zir.Inst.Ref.one_usize),
                as_u1 | @backingInt(Zir.Inst.Ref.undef_u1),
                as_u1 | @backingInt(Zir.Inst.Ref.zero_u1),
                as_u1 | @backingInt(Zir.Inst.Ref.one_u1),
                as_u8 | @backingInt(Zir.Inst.Ref.zero_u8),
                as_u8 | @backingInt(Zir.Inst.Ref.one_u8),
                as_u8 | @backingInt(Zir.Inst.Ref.four_u8),
                as_bool | @backingInt(Zir.Inst.Ref.undef_bool),
                as_bool | @backingInt(Zir.Inst.Ref.bool_true),
                as_bool | @backingInt(Zir.Inst.Ref.bool_false),
                as_void | @backingInt(Zir.Inst.Ref.void_value),
                => return result, // type of result is already correct

                as_bool | @backingInt(Zir.Inst.Ref.undef) => return .undef_bool,
                as_usize | @backingInt(Zir.Inst.Ref.undef) => return .undef_usize,
                as_usize | @backingInt(Zir.Inst.Ref.undef_u1) => return .undef_usize,
                as_u1 | @backingInt(Zir.Inst.Ref.undef) => return .undef_u1,

                as_usize | @backingInt(Zir.Inst.Ref.zero) => return .zero_usize,
                as_u1 | @backingInt(Zir.Inst.Ref.zero) => return .zero_u1,
                as_u8 | @backingInt(Zir.Inst.Ref.zero) => return .zero_u8,
                as_usize | @backingInt(Zir.Inst.Ref.one) => return .one_usize,
                as_u1 | @backingInt(Zir.Inst.Ref.one) => return .one_u1,
                as_u8 | @backingInt(Zir.Inst.Ref.one) => return .one_u8,
                as_comptime_int | @backingInt(Zir.Inst.Ref.zero_usize) => return .zero,
                as_u1 | @backingInt(Zir.Inst.Ref.zero_usize) => return .zero_u1,
                as_u8 | @backingInt(Zir.Inst.Ref.zero_usize) => return .zero_u8,
                as_comptime_int | @backingInt(Zir.Inst.Ref.one_usize) => return .one,
                as_u1 | @backingInt(Zir.Inst.Ref.one_usize) => return .one_u1,
                as_u8 | @backingInt(Zir.Inst.Ref.one_usize) => return .one_u8,
                as_comptime_int | @backingInt(Zir.Inst.Ref.zero_u1) => return .zero,
                as_comptime_int | @backingInt(Zir.Inst.Ref.zero_u8) => return .zero,
                as_usize | @backingInt(Zir.Inst.Ref.zero_u1) => return .zero_usize,
                as_usize | @backingInt(Zir.Inst.Ref.zero_u8) => return .zero_usize,
                as_comptime_int | @backingInt(Zir.Inst.Ref.one_u1) => return .one,
                as_comptime_int | @backingInt(Zir.Inst.Ref.one_u8) => return .one,
                as_usize | @backingInt(Zir.Inst.Ref.one_u1) => return .one_usize,
                as_usize | @backingInt(Zir.Inst.Ref.one_u8) => return .one_usize,

                // Need an explicit type coercion instruction.
                else => return gz.addPlNode(ri.zirTag(), src_node, Zir.Inst.As{
                    .dest_type = ty_inst,
                    .operand = result,
                }),
            }
        },
        .ptr => |ptr_res| {
            _ = try gz.addPlNode(.store_node, ptr_res.src_node orelse src_node, Zir.Inst.Bin{
                .lhs = ptr_res.inst,
                .rhs = result,
            });
            return .void_value;
        },
        .inferred_ptr => |alloc| {
            _ = try gz.addPlNode(.store_to_inferred_ptr, src_node, Zir.Inst.Bin{
                .lhs = alloc,
                .rhs = result,
            });
            return .void_value;
        },
        .destructure => |destructure| {
            const components = destructure.components;
            _ = try gz.addPlNode(.validate_destructure, src_node, Zir.Inst.ValidateDestructure{
                .operand = result,
                .destructure_node = gz.nodeIndexToRelative(destructure.src_node),
                .expect_len = @intCast(components.len),
            });
            for (components, 0..) |component, i| {
                if (component == .discard) continue;
                const elem_val = try gz.add(.{
                    .tag = .elem_val_imm,
                    .data = .{ .elem_val_imm = .{
                        .operand = result,
                        .idx = @intCast(i),
                    } },
                });
                switch (component) {
                    .typed_ptr => |ptr_res| {
                        _ = try gz.addPlNode(.store_node, ptr_res.src_node orelse src_node, Zir.Inst.Bin{
                            .lhs = ptr_res.inst,
                            .rhs = elem_val,
                        });
                    },
                    .inferred_ptr => |ptr_inst| {
                        _ = try gz.addPlNode(.store_to_inferred_ptr, src_node, Zir.Inst.Bin{
                            .lhs = ptr_inst,
                            .rhs = elem_val,
                        });
                    },
                    .discard => unreachable,
                }
            }
            return .void_value;
        },
    }
}