mirror of
https://github.com/ziglang/zig.git
synced 2026-01-20 14:25:16 +00:00
frontend: replace field_val and field_val_named
with field_ptr_load and field_ptr_named_load. These avoid doing by-val load operations for structs that are runtime-known while keeping the previous semantics for comptime-known values.
This commit is contained in:
parent
3bd62e1bb6
commit
354c17869a
@ -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]);
|
||||
|
||||
@ -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,
|
||||
|
||||
51
src/Sema.zig
51
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,
|
||||
|
||||
@ -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),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user