diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index 848f11ddce..304c3f6523 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -2731,9 +2731,9 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As .elem_val_node, .elem_val_imm, .field_ptr, - .field_val, + .field_ptr_load, .field_ptr_named, - .field_val_named, + .field_ptr_named_load, .func, .func_inferred, .func_fancy, @@ -6160,7 +6160,7 @@ fn fieldAccess( switch (ri.rl) { .ref, .ref_coerced_ty => return addFieldAccess(.field_ptr, gz, scope, .{ .rl = .ref }, node), else => { - const access = try addFieldAccess(.field_val, gz, scope, .{ .rl = .none }, node); + const access = try addFieldAccess(.field_ptr_load, gz, scope, .{ .rl = .ref }, node); return rvalue(gz, ri, access, node); }, } @@ -9286,17 +9286,21 @@ fn builtinCall( return rvalue(gz, ri, result, node); }, .field => { - if (ri.rl == .ref or ri.rl == .ref_coerced_ty) { - return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{ - .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]), - .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name), - }); + switch (ri.rl) { + .ref, .ref_coerced_ty => { + return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{ + .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]), + .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name), + }); + }, + else => { + const result = try gz.addPlNode(.field_ptr_named_load, node, Zir.Inst.FieldNamed{ + .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]), + .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name), + }); + return rvalue(gz, ri, result, node); + }, } - const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{ - .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]), - .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1], .field_name), - }); - return rvalue(gz, ri, result, node); }, .FieldType => { const ty_inst = try typeExpr(gz, scope, params[0]); diff --git a/lib/std/zig/Zir.zig b/lib/std/zig/Zir.zig index e4728dc7ad..3028426665 100644 --- a/lib/std/zig/Zir.zig +++ b/lib/std/zig/Zir.zig @@ -420,6 +420,7 @@ pub const Inst = struct { /// is the local's value. dbg_var_val, /// Uses a name to identify a Decl and takes a pointer to it. + /// /// Uses the `str_tok` union field. decl_ref, /// Uses a name to identify a Decl and uses it as a value. @@ -472,19 +473,26 @@ pub const Inst = struct { /// to the named field. The field name is stored in string_bytes. Used by a.b syntax. /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field. field_ptr, - /// Given a struct or object that contains virtual fields, returns the named field. + /// Given a pointer to a struct or object that contains virtual fields, loads from the + /// named field. + /// /// The field name is stored in string_bytes. Used by a.b syntax. + /// /// This instruction also accepts a pointer. + /// /// Uses `pl_node` field. The AST node is the a.b syntax. Payload is Field. - field_val, + field_ptr_load, /// Given a pointer to a struct or object that contains virtual fields, returns a pointer /// to the named field. The field name is a comptime instruction. Used by @field. /// Uses `pl_node` field. The AST node is the builtin call. Payload is FieldNamed. field_ptr_named, - /// Given a struct or object that contains virtual fields, returns the named field. + /// Given a pointer to a struct or object that contains virtual fields, + /// loads from the named field. + /// /// The field name is a comptime instruction. Used by @field. + /// /// Uses `pl_node` field. The AST node is the builtin call. Payload is FieldNamed. - field_val_named, + field_ptr_named_load, /// Returns a function type, or a function instance, depending on whether /// the body_len is 0. Calling convention is auto. /// Uses the `pl_node` union field. `payload_index` points to a `Func`. @@ -1145,9 +1153,9 @@ pub const Inst = struct { .ensure_err_union_payload_void, .@"export", .field_ptr, - .field_val, + .field_ptr_load, .field_ptr_named, - .field_val_named, + .field_ptr_named_load, .func, .func_inferred, .func_fancy, @@ -1435,9 +1443,9 @@ pub const Inst = struct { .elem_val_node, .elem_val_imm, .field_ptr, - .field_val, + .field_ptr_load, .field_ptr_named, - .field_val_named, + .field_ptr_named_load, .func, .func_inferred, .func_fancy, @@ -1688,9 +1696,9 @@ pub const Inst = struct { .error_value = .str_tok, .@"export" = .pl_node, .field_ptr = .pl_node, - .field_val = .pl_node, + .field_ptr_load = .pl_node, .field_ptr_named = .pl_node, - .field_val_named = .pl_node, + .field_ptr_named_load = .pl_node, .func = .pl_node, .func_inferred = .pl_node, .func_fancy = .pl_node, @@ -4225,9 +4233,9 @@ fn findTrackableInner( .error_value, .@"export", .field_ptr, - .field_val, + .field_ptr_load, .field_ptr_named, - .field_val_named, + .field_ptr_named_load, .import, .int, .int_big, diff --git a/src/Sema.zig b/src/Sema.zig index 439f0d0fc4..4e0167180e 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1187,7 +1187,7 @@ fn analyzeBodyInner( .cmp_gte => try sema.zirCmp(block, inst, .gte), .cmp_gt => try sema.zirCmp(block, inst, .gt), .cmp_neq => try sema.zirCmpEq(block, inst, .neq, Air.Inst.Tag.fromCmpOp(.neq, block.float_mode == .optimized)), - .decl_ref => try sema.zirDeclRef(block, inst), + .decl_ref => try sema.zirDeclRef(block, inst, true), .decl_val => try sema.zirDeclVal(block, inst), .load => try sema.zirLoad(block, inst), .elem_ptr => try sema.zirElemPtr(block, inst), @@ -1211,8 +1211,8 @@ fn analyzeBodyInner( .error_value => try sema.zirErrorValue(block, inst), .field_ptr => try sema.zirFieldPtr(block, inst), .field_ptr_named => try sema.zirFieldPtrNamed(block, inst), - .field_val => try sema.zirFieldVal(block, inst), - .field_val_named => try sema.zirFieldValNamed(block, inst), + .field_ptr_load => try sema.zirFieldPtrLoad(block, inst), + .field_ptr_named_load => try sema.zirFieldPtrNamedLoad(block, inst), .func => try sema.zirFunc(block, inst, false), .func_inferred => try sema.zirFunc(block, inst, true), .func_fancy => try sema.zirFuncFancy(block, inst), @@ -6524,7 +6524,7 @@ pub fn appendAirString(sema: *Sema, str: []const u8) Allocator.Error!Air.NullTer return nts; } -fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index, escape: bool) CompileError!Air.Inst.Ref { const pt = sema.pt; const zcu = pt.zcu; const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].str_tok; @@ -6536,7 +6536,7 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air .no_embedded_nulls, ); const nav_index = try sema.lookupIdentifier(block, decl_name); - return sema.analyzeNavRef(block, src, nav_index); + return sema.analyzeNavRefInner(block, src, nav_index, escape); } fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -9711,7 +9711,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! return block.addBitCast(dest_ty, operand); } -fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFieldPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -9727,8 +9727,8 @@ fn zirFieldVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai sema.code.nullTerminatedString(extra.field_name_start), .no_embedded_nulls, ); - const object = try sema.resolveInst(extra.lhs); - return sema.fieldVal(block, src, object, field_name, field_name_src); + const object_ptr = try sema.resolveInst(extra.lhs); + return fieldPtrLoad(sema, block, src, object_ptr, field_name, field_name_src); } fn zirFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -9779,7 +9779,7 @@ fn zirStructInitFieldPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi } } -fn zirFieldValNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { +fn zirFieldPtrNamedLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -9787,9 +9787,9 @@ fn zirFieldValNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr const src = block.nodeOffset(inst_data.src_node); const field_name_src = block.builtinCallArgSrc(inst_data.src_node, 1); const extra = sema.code.extraData(Zir.Inst.FieldNamed, inst_data.payload_index).data; - const object = try sema.resolveInst(extra.lhs); + const object_ptr = try sema.resolveInst(extra.lhs); const field_name = try sema.resolveConstStringIntern(block, field_name_src, extra.field_name, .{ .simple = .field_name }); - return sema.fieldVal(block, src, object, field_name, field_name_src); + return fieldPtrLoad(sema, block, src, object_ptr, field_name, field_name_src); } fn zirFieldPtrNamed(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { @@ -13612,7 +13612,6 @@ fn maybeErrorUnwrap( .str, .as_node, .panic, - .field_val, => {}, else => return false, } @@ -13631,7 +13630,6 @@ fn maybeErrorUnwrap( }, .str => try sema.zirStr(inst), .as_node => try sema.zirAsNode(block, inst), - .field_val => try sema.zirFieldVal(block, inst), .@"unreachable" => { try safetyPanicUnwrapError(sema, block, operand_src, operand); return true; @@ -26673,6 +26671,33 @@ fn emitBackwardBranch(sema: *Sema, block: *Block, src: LazySrcLoc) !void { } } +fn fieldPtrLoad( + sema: *Sema, + block: *Block, + src: LazySrcLoc, + object_ptr: Air.Inst.Ref, + field_name: InternPool.NullTerminatedString, + field_name_src: LazySrcLoc, +) CompileError!Air.Inst.Ref { + const pt = sema.pt; + const zcu = pt.zcu; + const object_ptr_ty = sema.typeOf(object_ptr); + const pointee_ty = object_ptr_ty.childType(zcu); + if (try typeHasOnePossibleValue(sema, pointee_ty)) |opv| { + const object: Air.Inst.Ref = .fromValue(opv); + return fieldVal(sema, block, src, object, field_name, field_name_src); + } + + if (try sema.resolveDefinedValue(block, src, object_ptr)) |object_ptr_val| { + if (try sema.pointerDeref(block, src, object_ptr_val, object_ptr_ty)) |object_val| { + const object: Air.Inst.Ref = .fromValue(object_val); + return fieldVal(sema, block, src, object, field_name, field_name_src); + } + } + const field_ptr = try sema.fieldPtr(block, src, object_ptr, field_name, field_name_src, false); + return analyzeLoad(sema, block, src, field_ptr, field_name_src); +} + fn fieldVal( sema: *Sema, block: *Block, diff --git a/src/print_zir.zig b/src/print_zir.zig index f875aaa552..490bba5c19 100644 --- a/src/print_zir.zig +++ b/src/print_zir.zig @@ -450,14 +450,14 @@ const Writer = struct { .switch_block_err_union => try self.writeSwitchBlockErrUnion(stream, inst), - .field_val, + .field_ptr_load, .field_ptr, .decl_literal, .decl_literal_no_coerce, => try self.writePlNodeField(stream, inst), .field_ptr_named, - .field_val_named, + .field_ptr_named_load, => try self.writePlNodeFieldNamed(stream, inst), .as_node, .as_shift_operand => try self.writeAs(stream, inst),