diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2025-09-21 01:49:28 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-21 01:49:28 -0700 |
| commit | 010d9a63f20d8a4bd14cff0ada690b2d127a0371 (patch) | |
| tree | 12b56ddfe5a5b235ef0676832902a0b04ad7d57a /src/Sema.zig | |
| parent | 3fbb88c4bd146ca7bd9e7ab5da9c4b05298f3b34 (diff) | |
| parent | 633162eb0c8d302ba7585cd308e01237409f042e (diff) | |
| download | zig-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.zig | 140 |
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", .{}); } |
