aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2025-09-21 01:49:28 -0700
committerGitHub <noreply@github.com>2025-09-21 01:49:28 -0700
commit010d9a63f20d8a4bd14cff0ada690b2d127a0371 (patch)
tree12b56ddfe5a5b235ef0676832902a0b04ad7d57a /src/Sema.zig
parent3fbb88c4bd146ca7bd9e7ab5da9c4b05298f3b34 (diff)
parent633162eb0c8d302ba7585cd308e01237409f042e (diff)
downloadzig-010d9a63f20d8a4bd14cff0ada690b2d127a0371.tar.gz
zig-010d9a63f20d8a4bd14cff0ada690b2d127a0371.zip
Merge pull request #25154 from ziglang/no-decl-val-3
rework byval ZIR instructions; forbid runtime vector indexes
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig140
1 files changed, 88 insertions, 52 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 385e1ae74a..946e890ea3 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -1193,7 +1193,7 @@ fn analyzeBodyInner(
.elem_ptr => try sema.zirElemPtr(block, inst),
.elem_ptr_node => try sema.zirElemPtrNode(block, inst),
.elem_val => try sema.zirElemVal(block, inst),
- .elem_val_node => try sema.zirElemValNode(block, inst),
+ .elem_ptr_load => try sema.zirElemPtrLoad(block, inst),
.elem_val_imm => try sema.zirElemValImm(block, inst),
.elem_type => try sema.zirElemType(block, inst),
.indexable_ptr_elem_type => try sema.zirIndexablePtrElemType(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),
@@ -3756,9 +3756,9 @@ fn zirAllocExtended(
const pt = sema.pt;
const gpa = sema.gpa;
const extra = sema.code.extraData(Zir.Inst.AllocExtended, extended.operand);
+ const var_src = block.nodeOffset(extra.data.src_node);
const ty_src = block.src(.{ .node_offset_var_decl_ty = extra.data.src_node });
const align_src = block.src(.{ .node_offset_var_decl_align = extra.data.src_node });
- const init_src = block.src(.{ .node_offset_var_decl_init = extra.data.src_node });
const small: Zir.Inst.AllocExtended.Small = @bitCast(extended.small);
var extra_index: usize = extra.end;
@@ -3777,7 +3777,7 @@ fn zirAllocExtended(
if (block.isComptime() or small.is_comptime) {
if (small.has_type) {
- return sema.analyzeComptimeAlloc(block, init_src, var_ty, alignment);
+ return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment);
} else {
try sema.air_instructions.append(gpa, .{
.tag = .inferred_alloc_comptime,
@@ -3792,7 +3792,7 @@ fn zirAllocExtended(
}
if (small.has_type and try var_ty.comptimeOnlySema(pt)) {
- return sema.analyzeComptimeAlloc(block, init_src, var_ty, alignment);
+ return sema.analyzeComptimeAlloc(block, var_src, var_ty, alignment);
}
if (small.has_type) {
@@ -3802,8 +3802,8 @@ fn zirAllocExtended(
const target = pt.zcu.getTarget();
try var_ty.resolveLayout(pt);
if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) {
- const var_src = block.src(.{ .node_offset_store_ptr = extra.data.src_node });
- return sema.fail(block, var_src, "local variable in naked function", .{});
+ const store_src = block.src(.{ .node_offset_store_ptr = extra.data.src_node });
+ return sema.fail(block, store_src, "local variable in naked function", .{});
}
const ptr_type = try sema.pt.ptrTypeSema(.{
.child = var_ty.toIntern(),
@@ -3842,9 +3842,9 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node });
- const init_src = block.src(.{ .node_offset_var_decl_init = inst_data.src_node });
+ const var_src = block.nodeOffset(inst_data.src_node);
const var_ty = try sema.resolveType(block, ty_src, inst_data.operand);
- return sema.analyzeComptimeAlloc(block, init_src, var_ty, .none);
+ return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none);
}
fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -4254,11 +4254,11 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node });
- const init_src = block.src(.{ .node_offset_var_decl_init = inst_data.src_node });
+ const var_src = block.nodeOffset(inst_data.src_node);
const var_ty = try sema.resolveType(block, ty_src, inst_data.operand);
if (block.isComptime() or try var_ty.comptimeOnlySema(pt)) {
- return sema.analyzeComptimeAlloc(block, init_src, var_ty, .none);
+ return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none);
}
if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) {
const mut_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node });
@@ -4284,14 +4284,14 @@ fn zirAllocMut(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
const ty_src = block.src(.{ .node_offset_var_decl_ty = inst_data.src_node });
- const init_src = block.src(.{ .node_offset_var_decl_init = inst_data.src_node });
+ const var_src = block.nodeOffset(inst_data.src_node);
const var_ty = try sema.resolveType(block, ty_src, inst_data.operand);
if (block.isComptime()) {
- return sema.analyzeComptimeAlloc(block, init_src, var_ty, .none);
+ return sema.analyzeComptimeAlloc(block, var_src, var_ty, .none);
}
if (sema.func_is_naked and try var_ty.hasRuntimeBitsSema(pt)) {
- const var_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node });
- return sema.fail(block, var_src, "local variable in naked function", .{});
+ const store_src = block.src(.{ .node_offset_store_ptr = inst_data.src_node });
+ return sema.fail(block, store_src, "local variable in naked function", .{});
}
try sema.validateVarType(block, ty_src, var_ty, false);
const target = pt.zcu.getTarget();
@@ -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 {
@@ -10102,7 +10102,7 @@ fn zirElemVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
return sema.elemVal(block, src, array, elem_index, src, false);
}
-fn zirElemValNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
+fn zirElemPtrLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const tracy = trace(@src());
defer tracy.end();
@@ -10110,10 +10110,18 @@ fn zirElemValNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const src = block.nodeOffset(inst_data.src_node);
const elem_index_src = block.src(.{ .node_offset_array_access_index = inst_data.src_node });
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
- const array = try sema.resolveInst(extra.lhs);
+ const array_ptr = try sema.resolveInst(extra.lhs);
const uncoerced_elem_index = try sema.resolveInst(extra.rhs);
+ if (try sema.resolveDefinedValue(block, src, array_ptr)) |array_ptr_val| {
+ const array_ptr_ty = sema.typeOf(array_ptr);
+ if (try sema.pointerDeref(block, src, array_ptr_val, array_ptr_ty)) |array_val| {
+ const array: Air.Inst.Ref = .fromValue(array_val);
+ return elemVal(sema, block, src, array, uncoerced_elem_index, elem_index_src, true);
+ }
+ }
const elem_index = try sema.coerce(block, .usize, uncoerced_elem_index, elem_index_src);
- return sema.elemVal(block, src, array, elem_index, elem_index_src, true);
+ const elem_ptr = try elemPtr(sema, block, src, array_ptr, elem_index, elem_index_src, false, true);
+ return analyzeLoad(sema, block, src, elem_ptr, elem_index_src);
}
fn zirElemValImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -13612,7 +13620,6 @@ fn maybeErrorUnwrap(
.str,
.as_node,
.panic,
- .field_val,
=> {},
else => return false,
}
@@ -13631,7 +13638,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;
@@ -15996,7 +16002,6 @@ fn splat(sema: *Sema, ty: Type, val: Value) !Value {
fn analyzeArithmetic(
sema: *Sema,
block: *Block,
- /// TODO performance investigation: make this comptime?
zir_tag: Zir.Inst.Tag,
lhs: Air.Inst.Ref,
rhs: Air.Inst.Ref,
@@ -16195,6 +16200,11 @@ fn analyzePtrArithmetic(
const ptr_info = ptr_ty.ptrInfo(zcu);
assert(ptr_info.flags.size == .many or ptr_info.flags.size == .c);
+ if ((try sema.typeHasOnePossibleValue(.fromInterned(ptr_info.child))) != null) {
+ // Offset will be multiplied by zero, so result is the same as the base pointer.
+ return ptr;
+ }
+
const new_ptr_ty = t: {
// Calculate the new pointer alignment.
// This code is duplicated in `Type.elemPtrType`.
@@ -26673,6 +26683,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,
@@ -26892,7 +26929,7 @@ fn fieldPtr(
const ptr_info = object_ty.ptrInfo(zcu);
const new_ptr_ty = try pt.ptrTypeSema(.{
.child = Type.fromInterned(ptr_info.child).childType(zcu).toIntern(),
- .sentinel = if (object_ty.sentinel(zcu)) |s| s.toIntern() else .none,
+ .sentinel = if (inner_ty.sentinel(zcu)) |s| s.toIntern() else .none,
.flags = .{
.size = .many,
.alignment = ptr_info.flags.alignment,
@@ -27420,15 +27457,9 @@ fn structFieldPtrByIndex(
if (struct_type.layout == .@"packed") {
assert(!field_is_comptime);
- switch (struct_ty.packedStructFieldPtrInfo(struct_ptr_ty, field_index, pt)) {
- .bit_ptr => |packed_offset| {
- ptr_ty_data.flags.alignment = parent_align;
- ptr_ty_data.packed_offset = packed_offset;
- },
- .byte_ptr => |ptr_info| {
- ptr_ty_data.flags.alignment = ptr_info.alignment;
- },
- }
+ const packed_offset = struct_ty.packedStructFieldPtrInfo(struct_ptr_ty, field_index, pt);
+ ptr_ty_data.flags.alignment = parent_align;
+ ptr_ty_data.packed_offset = packed_offset;
} else if (struct_type.layout == .@"extern") {
assert(!field_is_comptime);
// For extern structs, field alignment might be bigger than type's
@@ -27972,6 +28003,7 @@ fn elemVal(
}
}
+/// Called when the index or indexable is runtime known.
fn validateRuntimeElemAccess(
sema: *Sema,
block: *Block,
@@ -28236,6 +28268,10 @@ fn elemPtrArray(
try sema.validateRuntimeValue(block, array_ptr_src, array_ptr);
}
+ if (offset == null and array_ty.zigTypeTag(zcu) == .vector) {
+ return sema.fail(block, elem_index_src, "vector index not comptime known", .{});
+ }
+
// Runtime check is only needed if unable to comptime check.
if (oob_safety and block.wantSafety() and offset == null) {
const len_inst = try pt.intRef(.usize, array_len);
@@ -30634,6 +30670,19 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul
} };
return false;
}
+
+ if (inst_info.packed_offset.host_size != dest_info.packed_offset.host_size or
+ inst_info.packed_offset.bit_offset != dest_info.packed_offset.bit_offset)
+ {
+ in_memory_result.* = .{ .ptr_bit_range = .{
+ .actual_host = inst_info.packed_offset.host_size,
+ .wanted_host = dest_info.packed_offset.host_size,
+ .actual_offset = inst_info.packed_offset.bit_offset,
+ .wanted_offset = dest_info.packed_offset.bit_offset,
+ } };
+ return false;
+ }
+
return true;
}
@@ -31425,19 +31474,6 @@ fn analyzeLoad(
}
}
- if (ptr_ty.ptrInfo(zcu).flags.vector_index == .runtime) {
- const ptr_inst = ptr.toIndex().?;
- const air_tags = sema.air_instructions.items(.tag);
- if (air_tags[@intFromEnum(ptr_inst)] == .ptr_elem_ptr) {
- const ty_pl = sema.air_instructions.items(.data)[@intFromEnum(ptr_inst)].ty_pl;
- const bin_op = sema.getTmpAir().extraData(Air.Bin, ty_pl.payload).data;
- return block.addBinOp(.ptr_elem_val, bin_op.lhs, bin_op.rhs);
- }
- return sema.fail(block, ptr_src, "unable to determine vector element index of type '{f}'", .{
- ptr_ty.fmt(pt),
- });
- }
-
return block.addTyOp(.load, elem_ty, ptr);
}
@@ -34954,7 +34990,7 @@ fn resolveInferredErrorSet(
const resolved_ty = func.resolvedErrorSetUnordered(ip);
if (resolved_ty != .none) return resolved_ty;
- if (zcu.analysis_in_progress.contains(AnalUnit.wrap(.{ .func = func_index }))) {
+ if (zcu.analysis_in_progress.contains(.wrap(.{ .func = func_index }))) {
return sema.fail(block, src, "unable to resolve inferred error set", .{});
}