From 85c69c51945d7fb5d4cd2dea03fdb7915ecc55fa Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 3 May 2023 20:04:47 -0700 Subject: [PATCH] Type.isSlice: make it InternPool aware --- src/InternPool.zig | 50 ++++- src/Sema.zig | 56 ++--- src/TypedValue.zig | 2 +- src/arch/aarch64/abi.zig | 2 +- src/arch/arm/abi.zig | 2 +- src/arch/riscv64/abi.zig | 2 +- src/arch/wasm/CodeGen.zig | 20 +- src/arch/wasm/abi.zig | 2 +- src/arch/x86_64/CodeGen.zig | 4 +- src/codegen.zig | 10 +- src/codegen/c.zig | 16 +- src/codegen/llvm.zig | 15 +- src/codegen/spirv.zig | 4 +- src/link/Dwarf.zig | 2 +- src/type.zig | 429 ++++++++++++++++++------------------ src/value.zig | 8 +- 16 files changed, 339 insertions(+), 285 deletions(-) diff --git a/src/InternPool.zig b/src/InternPool.zig index 6345d36f26..3ecc18c426 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -629,7 +629,7 @@ pub const Tag = enum(u8) { /// A vector type. /// data is payload to Vector. type_vector, - /// A pointer type along with all its bells and whistles. + /// A fully explicitly specified pointer type. /// data is payload to Pointer. type_pointer, /// An optional type. @@ -682,13 +682,13 @@ pub const Tag = enum(u8) { /// An enum tag identified by a negative integer value. /// data is a limbs index to Int. enum_tag_negative, - /// A float value that can be represented by f32. + /// An f32 value. /// data is float value bitcasted to u32. float_f32, - /// A float value that can be represented by f64. + /// An f64 value. /// data is payload index to Float64. float_f64, - /// A float value that can be represented by f128. + /// An f128 value. /// data is payload index to Float128. float_f128, /// An extern function. @@ -871,7 +871,47 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { .simple_type => .{ .simple_type = @intToEnum(SimpleType, data) }, .simple_value => .{ .simple_value = @intToEnum(SimpleValue, data) }, - else => @panic("TODO"), + .type_vector => { + const vector_info = ip.extraData(Vector, data); + return .{ .vector_type = .{ + .len = vector_info.len, + .child = vector_info.child, + } }; + }, + + .type_pointer => { + const ptr_info = ip.extraData(Pointer, data); + return .{ .ptr_type = .{ + .elem_type = ptr_info.child, + .sentinel = ptr_info.sentinel, + .alignment = ptr_info.flags.alignment, + .size = ptr_info.flags.size, + .is_const = ptr_info.flags.is_const, + .is_volatile = ptr_info.flags.is_volatile, + .is_allowzero = ptr_info.flags.is_allowzero, + .address_space = ptr_info.flags.address_space, + } }; + }, + + .type_optional => .{ .optional_type = .{ .payload_type = @intToEnum(Index, data) } }, + + .type_error_union => @panic("TODO"), + .type_enum_simple => @panic("TODO"), + .simple_internal => @panic("TODO"), + .int_small_u32 => @panic("TODO"), + .int_small_i32 => @panic("TODO"), + .int_small_usize => @panic("TODO"), + .int_small_comptime_unsigned => @panic("TODO"), + .int_small_comptime_signed => @panic("TODO"), + .int_positive => @panic("TODO"), + .int_negative => @panic("TODO"), + .enum_tag_positive => @panic("TODO"), + .enum_tag_negative => @panic("TODO"), + .float_f32 => @panic("TODO"), + .float_f64 => @panic("TODO"), + .float_f128 => @panic("TODO"), + .extern_func => @panic("TODO"), + .func => @panic("TODO"), }; } diff --git a/src/Sema.zig b/src/Sema.zig index 65475104aa..0eecda5d16 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -2030,7 +2030,7 @@ fn failWithArrayInitNotSupported(sema: *Sema, block: *Block, src: LazySrcLoc, ty ty.fmt(mod), }); errdefer msg.destroy(sema.gpa); - if (ty.isSlice()) { + if (ty.isSlice(mod)) { try sema.errNote(block, src, msg, "inferred array length is specified with an underscore: '[_]{}'", .{ty.elemType2(mod).fmt(mod)}); } break :msg msg; @@ -10359,7 +10359,7 @@ fn zirSwitchCond( .ErrorSet, .Enum, => { - if (operand_ty.isSlice()) { + if (operand_ty.isSlice(mod)) { return sema.fail(block, src, "switch on type '{}'", .{operand_ty.fmt(sema.mod)}); } if ((try sema.typeHasOnePossibleValue(operand_ty))) |opv| { @@ -12017,7 +12017,7 @@ fn zirHasField(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const ty = try sema.resolveTypeFields(unresolved_ty); const has_field = hf: { - if (ty.isSlice()) { + if (ty.isSlice(mod)) { if (mem.eql(u8, field_name, "ptr")) break :hf true; if (mem.eql(u8, field_name, "len")) break :hf true; break :hf false; @@ -20020,8 +20020,8 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air return sema.failWithOwnedErrorMsg(msg); } - const dest_is_slice = dest_ty.isSlice(); - const operand_is_slice = operand_ty.isSlice(); + const dest_is_slice = dest_ty.isSlice(mod); + const operand_is_slice = operand_ty.isSlice(mod); if (dest_is_slice and !operand_is_slice) { return sema.fail(block, dest_ty_src, "illegal pointer cast to slice", .{}); } @@ -20274,14 +20274,14 @@ fn zirAlignCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A Type.usize, Value.initPayload(&val_payload.base), ); - const actual_ptr = if (ptr_ty.isSlice()) + const actual_ptr = if (ptr_ty.isSlice(mod)) try sema.analyzeSlicePtr(block, ptr_src, ptr, ptr_ty) else ptr; const ptr_int = try block.addUnOp(.ptrtoint, actual_ptr); const remainder = try block.addBinOp(.bit_and, ptr_int, align_minus_1); const is_aligned = try block.addBinOp(.cmp_eq, remainder, .zero_usize); - const ok = if (ptr_ty.isSlice()) ok: { + const ok = if (ptr_ty.isSlice(mod)) ok: { const len = try sema.analyzeSliceLen(block, ptr_src, ptr); const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize); break :ok try block.addBinOp(.bit_or, len_zero, is_aligned); @@ -22336,7 +22336,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void // Change the src from slice to a many pointer, to avoid multiple ptr // slice extractions in AIR instructions. const new_src_ptr_ty = sema.typeOf(new_src_ptr); - if (new_src_ptr_ty.isSlice()) { + if (new_src_ptr_ty.isSlice(mod)) { new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty); } } else if (dest_len == .none and len_val == null) { @@ -22344,7 +22344,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void const dest_ptr_ptr = try sema.analyzeRef(block, dest_src, new_dest_ptr); new_dest_ptr = try sema.analyzeSlice(block, dest_src, dest_ptr_ptr, .zero, src_len, .none, .unneeded, dest_src, dest_src, dest_src, false); const new_src_ptr_ty = sema.typeOf(new_src_ptr); - if (new_src_ptr_ty.isSlice()) { + if (new_src_ptr_ty.isSlice(mod)) { new_src_ptr = try sema.analyzeSlicePtr(block, src_src, new_src_ptr, new_src_ptr_ty); } } @@ -22363,7 +22363,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void // Extract raw pointer from dest slice. The AIR instructions could support them, but // it would cause redundant machine code instructions. const new_dest_ptr_ty = sema.typeOf(new_dest_ptr); - const raw_dest_ptr = if (new_dest_ptr_ty.isSlice()) + const raw_dest_ptr = if (new_dest_ptr_ty.isSlice(mod)) try sema.analyzeSlicePtr(block, dest_src, new_dest_ptr, new_dest_ptr_ty) else new_dest_ptr; @@ -23383,7 +23383,7 @@ fn validateExternType( .Float, .AnyFrame, => return true, - .Pointer => return !(ty.isSlice() or try sema.typeRequiresComptime(ty)), + .Pointer => return !(ty.isSlice(mod) or try sema.typeRequiresComptime(ty)), .Int => switch (ty.intInfo(mod).bits) { 8, 16, 32, 64, 128 => return true, else => return false, @@ -23448,7 +23448,7 @@ fn explainWhyTypeIsNotExtern( => return, .Pointer => { - if (ty.isSlice()) { + if (ty.isSlice(mod)) { try mod.errNoteNonLazy(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); } else { const pointee_ty = ty.childType(); @@ -23523,7 +23523,7 @@ fn validatePackedType(ty: Type, mod: *const Module) bool { .Vector, .Enum, => return true, - .Pointer => return !ty.isSlice(), + .Pointer => return !ty.isSlice(mod), .Struct, .Union => return ty.containerLayout() == .Packed, } } @@ -23803,7 +23803,7 @@ fn panicSentinelMismatch( const expected_sentinel = try sema.addConstant(sentinel_ty, expected_sentinel_val); const ptr_ty = sema.typeOf(ptr); - const actual_sentinel = if (ptr_ty.isSlice()) + const actual_sentinel = if (ptr_ty.isSlice(mod)) try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index) else blk: { const elem_ptr_ty = try sema.elemPtrType(ptr_ty, null); @@ -24064,7 +24064,7 @@ fn fieldVal( const msg = msg: { const msg = try sema.errMsg(block, src, "type '{}' has no members", .{child_type.fmt(sema.mod)}); errdefer msg.destroy(sema.gpa); - if (child_type.isSlice()) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{}); + if (child_type.isSlice(mod)) try sema.errNote(block, src, msg, "slice values have 'len' and 'ptr' members", .{}); if (child_type.zigTypeTag(mod) == .Array) try sema.errNote(block, src, msg, "array values have 'len' member", .{}); break :msg msg; }; @@ -24140,7 +24140,7 @@ fn fieldPtr( ); } }, - .Pointer => if (inner_ty.isSlice()) { + .Pointer => if (inner_ty.isSlice(mod)) { const inner_ptr = if (is_pointer_to) try sema.analyzeLoad(block, src, object_ptr, object_ptr_src) else @@ -25743,8 +25743,8 @@ fn coerceExtra( } }; break :pointer; } - if (dest_ty.isSlice()) break :to_anyopaque; - if (inst_ty.isSlice()) { + if (dest_ty.isSlice(mod)) break :to_anyopaque; + if (inst_ty.isSlice(mod)) { in_memory_result = .{ .slice_to_anyopaque = .{ .actual = inst_ty, .wanted = dest_ty, @@ -25885,7 +25885,7 @@ fn coerceExtra( return sema.coerceTupleToSlicePtrs(block, dest_ty, dest_ty_src, inst, inst_src); }, .Many => p: { - if (!inst_ty.isSlice()) break :p; + if (!inst_ty.isSlice(mod)) break :p; if (!sema.checkPtrAttributes(dest_ty, inst_ty, &in_memory_result)) break :p; const inst_info = inst_ty.ptrInfo().data; @@ -26651,7 +26651,7 @@ fn coerceInMemoryAllowed( } // Slices - if (dest_ty.isSlice() and src_ty.isSlice()) { + if (dest_ty.isSlice(mod) and src_ty.isSlice(mod)) { return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src); } @@ -27744,7 +27744,7 @@ fn beginComptimePtrMutation( ); }, .Pointer => { - assert(parent.ty.isSlice()); + assert(parent.ty.isSlice(mod)); val_ptr.* = try Value.Tag.slice.create(arena, .{ .ptr = Value.undef, .len = Value.undef, @@ -28187,7 +28187,7 @@ fn beginComptimePtrLoad( break :blk deref; } - if (field_ptr.container_ty.isSlice()) { + if (field_ptr.container_ty.isSlice(mod)) { const slice_val = tv.val.castTag(.slice).?.data; deref.pointee = switch (field_index) { Value.Payload.Slice.ptr_index => TypedValue{ @@ -28442,13 +28442,13 @@ fn coerceCompatiblePtrs( if (block.wantSafety() and inst_allows_zero and !dest_ty.ptrAllowsZero(mod) and (try sema.typeHasRuntimeBits(dest_ty.elemType2(mod)) or dest_ty.elemType2(mod).zigTypeTag(mod) == .Fn)) { - const actual_ptr = if (inst_ty.isSlice()) + const actual_ptr = if (inst_ty.isSlice(mod)) try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty) else inst; const ptr_int = try block.addUnOp(.ptrtoint, actual_ptr); const is_non_zero = try block.addBinOp(.cmp_neq, ptr_int, .zero_usize); - const ok = if (inst_ty.isSlice()) ok: { + const ok = if (inst_ty.isSlice(mod)) ok: { const len = try sema.analyzeSliceLen(block, inst_src, inst); const len_zero = try block.addBinOp(.cmp_eq, len, .zero_usize); break :ok try block.addBinOp(.bit_or, len_zero, is_non_zero); @@ -29548,7 +29548,7 @@ fn analyzeSlice( else => return sema.fail(block, src, "slice of non-array type '{}'", .{ptr_ptr_child_ty.fmt(mod)}), } - const ptr = if (slice_ty.isSlice()) + const ptr = if (slice_ty.isSlice(mod)) try sema.analyzeSlicePtr(block, ptr_src, ptr_or_slice, slice_ty) else ptr_or_slice; @@ -29605,7 +29605,7 @@ fn analyzeSlice( } break :e try sema.addConstant(Type.usize, len_val); - } else if (slice_ty.isSlice()) { + } else if (slice_ty.isSlice(mod)) { if (!end_is_len) { const end = if (by_length) end: { const len = try sema.coerce(block, Type.usize, uncasted_end_opt, end_src); @@ -29778,7 +29778,7 @@ fn analyzeSlice( try sema.addSafetyCheck(block, is_non_null, .unwrap_null); } - if (slice_ty.isSlice()) { + if (slice_ty.isSlice(mod)) { const slice_len_inst = try block.addTyOp(.slice_len, Type.usize, ptr_or_slice); const actual_len = if (slice_ty.sentinel() == null) slice_len_inst @@ -29840,7 +29840,7 @@ fn analyzeSlice( // requirement: end <= len const opt_len_inst = if (array_ty.zigTypeTag(mod) == .Array) try sema.addIntUnsigned(Type.usize, array_ty.arrayLenIncludingSentinel()) - else if (slice_ty.isSlice()) blk: { + else if (slice_ty.isSlice(mod)) blk: { if (try sema.resolveDefinedValue(block, src, ptr_or_slice)) |slice_val| { // we don't need to add one for sentinels because the // underlying value data includes the sentinel diff --git a/src/TypedValue.zig b/src/TypedValue.zig index 7302f42e57..877a8f5f4c 100644 --- a/src/TypedValue.zig +++ b/src/TypedValue.zig @@ -259,7 +259,7 @@ pub fn print( } else if (field_ptr.container_ty.zigTypeTag(mod) == .Union) { const field_name = field_ptr.container_ty.unionFields().keys()[field_ptr.field_index]; return writer.print(".{s}", .{field_name}); - } else if (field_ptr.container_ty.isSlice()) { + } else if (field_ptr.container_ty.isSlice(mod)) { switch (field_ptr.field_index) { Value.Payload.Slice.ptr_index => return writer.writeAll(".ptr"), Value.Payload.Slice.len_index => return writer.writeAll(".len"), diff --git a/src/arch/aarch64/abi.zig b/src/arch/aarch64/abi.zig index cbfd6a1171..821afd27ae 100644 --- a/src/arch/aarch64/abi.zig +++ b/src/arch/aarch64/abi.zig @@ -52,7 +52,7 @@ pub fn classifyType(ty: Type, mod: *const Module) Class { return .byval; }, .Pointer => { - std.debug.assert(!ty.isSlice()); + std.debug.assert(!ty.isSlice(mod)); return .byval; }, .ErrorUnion, diff --git a/src/arch/arm/abi.zig b/src/arch/arm/abi.zig index ca7fff7d08..eee4b41eef 100644 --- a/src/arch/arm/abi.zig +++ b/src/arch/arm/abi.zig @@ -94,7 +94,7 @@ pub fn classifyType(ty: Type, mod: *const Module, ctx: Context) Class { return .byval; }, .Pointer => { - assert(!ty.isSlice()); + assert(!ty.isSlice(mod)); return .byval; }, .ErrorUnion, diff --git a/src/arch/riscv64/abi.zig b/src/arch/riscv64/abi.zig index c9e0873bce..ac0d8d3e32 100644 --- a/src/arch/riscv64/abi.zig +++ b/src/arch/riscv64/abi.zig @@ -52,7 +52,7 @@ pub fn classifyType(ty: Type, mod: *const Module) Class { return .byval; }, .Pointer => { - std.debug.assert(!ty.isSlice()); + std.debug.assert(!ty.isSlice(mod)); return .byval; }, .ErrorUnion, diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index 2c1e8aa36d..bb3f1f769d 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -1773,7 +1773,7 @@ fn isByRef(ty: Type, mod: *const Module) bool { }, .Pointer => { // Slices act like struct and will be passed by reference - if (ty.isSlice()) return true; + if (ty.isSlice(mod)) return true; return false; }, } @@ -2396,7 +2396,7 @@ fn store(func: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerE }, }, .Pointer => { - if (ty.isSlice()) { + if (ty.isSlice(mod)) { // store pointer first // lower it to the stack so we do not have to store rhs into a local first try func.emitWValue(lhs); @@ -3010,11 +3010,11 @@ fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.In } fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: Module.Decl.Index, offset: u32) InnerError!WValue { - if (tv.ty.isSlice()) { + const mod = func.bin_file.base.options.module.?; + if (tv.ty.isSlice(mod)) { return WValue{ .memory = try func.bin_file.lowerUnnamedConst(tv, decl_index) }; } - const mod = func.bin_file.base.options.module.?; const decl = mod.declPtr(decl_index); if (decl.ty.zigTypeTag(mod) != .Fn and !decl.ty.hasRuntimeBitsIgnoreComptime(mod)) { return WValue{ .imm32 = 0xaaaaaaaa }; @@ -4182,7 +4182,7 @@ fn isNull(func: *CodeGen, operand: WValue, optional_ty: Type, opcode: wasm.Opcod }; try func.addMemArg(.i32_load8_u, .{ .offset = operand.offset() + offset, .alignment = 1 }); } - } else if (payload_ty.isSlice()) { + } else if (payload_ty.isSlice(mod)) { switch (func.arch()) { .wasm32 => try func.addMemArg(.i32_load, .{ .offset = operand.offset(), .alignment = 4 }), .wasm64 => try func.addMemArg(.i64_load, .{ .offset = operand.offset(), .alignment = 8 }), @@ -4455,10 +4455,11 @@ fn airArrayToSlice(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn airPtrToInt(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { + const mod = func.bin_file.base.options.module.?; const un_op = func.air.instructions.items(.data)[inst].un_op; const operand = try func.resolveInst(un_op); const ptr_ty = func.typeOf(un_op); - const result = if (ptr_ty.isSlice()) + const result = if (ptr_ty.isSlice(mod)) try func.slicePtr(operand) else switch (operand) { // for stack offset, return a pointer to this offset. @@ -4479,7 +4480,7 @@ fn airPtrElemVal(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const elem_size = elem_ty.abiSize(mod); // load pointer onto the stack - if (ptr_ty.isSlice()) { + if (ptr_ty.isSlice(mod)) { _ = try func.load(ptr, Type.usize, 0); } else { try func.lowerToStack(ptr); @@ -4518,7 +4519,7 @@ fn airPtrElemPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { const index = try func.resolveInst(bin_op.rhs); // load pointer onto the stack - if (ptr_ty.isSlice()) { + if (ptr_ty.isSlice(mod)) { _ = try func.load(ptr, Type.usize, 0); } else { try func.lowerToStack(ptr); @@ -5441,7 +5442,8 @@ fn airFieldParentPtr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void { } fn sliceOrArrayPtr(func: *CodeGen, ptr: WValue, ptr_ty: Type) InnerError!WValue { - if (ptr_ty.isSlice()) { + const mod = func.bin_file.base.options.module.?; + if (ptr_ty.isSlice(mod)) { return func.slicePtr(ptr); } else { return ptr; diff --git a/src/arch/wasm/abi.zig b/src/arch/wasm/abi.zig index 7dd4425c01..c7819b0fa6 100644 --- a/src/arch/wasm/abi.zig +++ b/src/arch/wasm/abi.zig @@ -60,7 +60,7 @@ pub fn classifyType(ty: Type, mod: *const Module) [2]Class { return direct; }, .Pointer => { - std.debug.assert(!ty.isSlice()); + std.debug.assert(!ty.isSlice(mod)); return direct; }, .Union => { diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 3e0ca4831b..ad67a0db3d 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -8688,7 +8688,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod)) - .{ .off = 0, .ty = if (pl_ty.isSlice()) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty } + .{ .off = 0, .ty = if (pl_ty.isSlice(mod)) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty } else .{ .off = @intCast(i32, pl_ty.abiSize(mod)), .ty = Type.bool }; @@ -8781,7 +8781,7 @@ fn isNullPtr(self: *Self, inst: Air.Inst.Index, ptr_ty: Type, ptr_mcv: MCValue) var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; const some_info: struct { off: i32, ty: Type } = if (opt_ty.optionalReprIsPayload(mod)) - .{ .off = 0, .ty = if (pl_ty.isSlice()) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty } + .{ .off = 0, .ty = if (pl_ty.isSlice(mod)) pl_ty.slicePtrFieldType(&ptr_buf) else pl_ty } else .{ .off = @intCast(i32, pl_ty.abiSize(mod)), .ty = Type.bool }; diff --git a/src/codegen.zig b/src/codegen.zig index a3ecf88d50..c9e2c6c265 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -317,11 +317,11 @@ pub fn generateSymbol( switch (target.ptrBitWidth()) { 32 => { mem.writeInt(u32, try code.addManyAsArray(4), 0, endian); - if (typed_value.ty.isSlice()) try code.appendNTimes(0xaa, 4); + if (typed_value.ty.isSlice(mod)) try code.appendNTimes(0xaa, 4); }, 64 => { mem.writeInt(u64, try code.addManyAsArray(8), 0, endian); - if (typed_value.ty.isSlice()) try code.appendNTimes(0xaa, 8); + if (typed_value.ty.isSlice(mod)) try code.appendNTimes(0xaa, 8); }, else => unreachable, } @@ -845,7 +845,7 @@ fn lowerParentPtr( debug_output, reloc_info.offset(@intCast(u32, switch (field_ptr.container_ty.zigTypeTag(mod)) { .Pointer => offset: { - assert(field_ptr.container_ty.isSlice()); + assert(field_ptr.container_ty.isSlice(mod)); var buf: Type.SlicePtrFieldTypeBuffer = undefined; break :offset switch (field_ptr.field_index) { 0 => 0, @@ -946,7 +946,7 @@ fn lowerDeclRef( ) CodeGenError!Result { const target = bin_file.options.target; const mod = bin_file.options.module.?; - if (typed_value.ty.isSlice()) { + if (typed_value.ty.isSlice(mod)) { // generate ptr var buf: Type.SlicePtrFieldTypeBuffer = undefined; const slice_ptr_field_type = typed_value.ty.slicePtrFieldType(&buf); @@ -1174,7 +1174,7 @@ pub fn genTypedValue( const target = bin_file.options.target; const ptr_bits = target.ptrBitWidth(); - if (!typed_value.ty.isSlice()) { + if (!typed_value.ty.isSlice(mod)) { if (typed_value.val.castTag(.variable)) |payload| { return genDeclRef(bin_file, src_loc, typed_value, payload.data.owner_decl); } diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 327ccb0119..cd4f36e574 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -556,7 +556,7 @@ pub const DeclGen = struct { if (decl.val.castTag(.variable)) |var_payload| try dg.renderFwdDecl(decl_index, var_payload.data); - if (ty.isSlice()) { + if (ty.isSlice(mod)) { if (location == .StaticInitializer) { try writer.writeByte('{'); } else { @@ -603,7 +603,7 @@ pub const DeclGen = struct { fn renderParentPtr(dg: *DeclGen, writer: anytype, ptr_val: Value, ptr_ty: Type, location: ValueRenderLocation) error{ OutOfMemory, AnalysisFail }!void { const mod = dg.module; - if (!ptr_ty.isSlice()) { + if (!ptr_ty.isSlice(mod)) { try writer.writeByte('('); try dg.renderType(writer, ptr_ty); try writer.writeByte(')'); @@ -776,7 +776,7 @@ pub const DeclGen = struct { try dg.renderValue(writer, repr_ty, Value.undef, .FunctionArgument); return writer.writeByte(')'); }, - .Pointer => if (ty.isSlice()) { + .Pointer => if (ty.isSlice(mod)) { if (!location.isInitializer()) { try writer.writeByte('('); try dg.renderType(writer, ty); @@ -1045,7 +1045,7 @@ pub const DeclGen = struct { return; }, .Pointer => switch (val.tag()) { - .null_value, .zero => if (ty.isSlice()) { + .null_value, .zero => if (ty.isSlice(mod)) { var slice_pl = Value.Payload.Slice{ .base = .{ .tag = .slice }, .data = .{ .ptr = val, .len = Value.undef }, @@ -5073,7 +5073,7 @@ fn airIsNull( TypedValue{ .ty = optional_ty, .val = Value.null } else if (payload_ty.zigTypeTag(mod) == .ErrorSet) TypedValue{ .ty = payload_ty, .val = Value.zero } - else if (payload_ty.isSlice() and optional_ty.optionalReprIsPayload(mod)) rhs: { + else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: { try writer.writeAll(".ptr"); const slice_ptr_ty = payload_ty.slicePtrFieldType(&slice_ptr_buf); break :rhs TypedValue{ .ty = slice_ptr_ty, .val = Value.null }; @@ -5864,6 +5864,7 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { } fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue { + const mod = f.object.dg.module; const un_op = f.air.instructions.items(.data)[inst].un_op; const operand = try f.resolveInst(un_op); @@ -5877,7 +5878,7 @@ fn airPtrToInt(f: *Function, inst: Air.Inst.Index) !CValue { try writer.writeAll(" = ("); try f.renderType(writer, inst_ty); try writer.writeByte(')'); - if (operand_ty.isSlice()) { + if (operand_ty.isSlice(mod)) { try f.writeCValueMember(writer, operand, .{ .identifier = "len" }); } else { try f.writeCValue(writer, operand, .Other); @@ -6272,7 +6273,8 @@ fn airAtomicStore(f: *Function, inst: Air.Inst.Index, order: [*:0]const u8) !CVa } fn writeSliceOrPtr(f: *Function, writer: anytype, ptr: CValue, ptr_ty: Type) !void { - if (ptr_ty.isSlice()) { + const mod = f.object.dg.module; + if (ptr_ty.isSlice(mod)) { try f.writeCValueMember(writer, ptr, .{ .identifier = "ptr" }); } else { try f.writeCValue(writer, ptr, .FunctionArgument); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 1a092dff69..5d9345c84f 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1636,7 +1636,7 @@ pub const Object = struct { return ptr_di_ty; } - if (ty.isSlice()) { + if (ty.isSlice(mod)) { var buf: Type.SlicePtrFieldTypeBuffer = undefined; const ptr_ty = ty.slicePtrFieldType(&buf); const len_ty = Type.usize; @@ -2833,7 +2833,7 @@ pub const DeclGen = struct { }, .Bool => return dg.context.intType(1), .Pointer => { - if (t.isSlice()) { + if (t.isSlice(mod)) { var buf: Type.SlicePtrFieldTypeBuffer = undefined; const ptr_type = t.slicePtrFieldType(&buf); @@ -4110,7 +4110,7 @@ pub const DeclGen = struct { } }, .Pointer => { - assert(parent_ty.isSlice()); + assert(parent_ty.isSlice(mod)); const indices: [2]*llvm.Value = .{ llvm_u32.constInt(0, .False), llvm_u32.constInt(field_index, .False), @@ -4184,7 +4184,7 @@ pub const DeclGen = struct { decl_index: Module.Decl.Index, ) Error!*llvm.Value { const mod = self.module; - if (tv.ty.isSlice()) { + if (tv.ty.isSlice(mod)) { var buf: Type.SlicePtrFieldTypeBuffer = undefined; const ptr_ty = tv.ty.slicePtrFieldType(&buf); var slice_len: Value.Payload.U64 = .{ @@ -5794,7 +5794,8 @@ pub const FuncGen = struct { } fn sliceOrArrayPtr(fg: *FuncGen, ptr: *llvm.Value, ty: Type) *llvm.Value { - if (ty.isSlice()) { + const mod = fg.dg.module; + if (ty.isSlice(mod)) { return fg.builder.buildExtractValue(ptr, 0, ""); } else { return ptr; @@ -6669,7 +6670,7 @@ pub const FuncGen = struct { self.builder.buildLoad(optional_llvm_ty, operand, "") else operand; - if (payload_ty.isSlice()) { + if (payload_ty.isSlice(mod)) { const slice_ptr = self.builder.buildExtractValue(loaded, 0, ""); var slice_buf: Type.SlicePtrFieldTypeBuffer = undefined; const ptr_ty = try self.dg.lowerType(payload_ty.slicePtrFieldType(&slice_buf)); @@ -10864,7 +10865,7 @@ const ParamTypeIterator = struct { it.zig_index += 1; it.llvm_index += 1; var buf: Type.Payload.ElemType = undefined; - if (ty.isSlice() or (ty.zigTypeTag(mod) == .Optional and ty.optionalChild(&buf).isSlice())) { + if (ty.isSlice(mod) or (ty.zigTypeTag(mod) == .Optional and ty.optionalChild(&buf).isSlice(mod))) { it.llvm_index += 1; return .slice; } else if (isByRef(ty, mod)) { diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 417a8035b5..f69c6cb317 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -2980,12 +2980,12 @@ pub const DeclGen = struct { // Pointer payload represents nullability: pointer or slice. var ptr_buf: Type.SlicePtrFieldTypeBuffer = undefined; - const ptr_ty = if (payload_ty.isSlice()) + const ptr_ty = if (payload_ty.isSlice(mod)) payload_ty.slicePtrFieldType(&ptr_buf) else payload_ty; - const ptr_id = if (payload_ty.isSlice()) + const ptr_id = if (payload_ty.isSlice(mod)) try self.extractField(Type.bool, operand_id, 0) else operand_id; diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 9c6e54ea98..682431203e 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -258,7 +258,7 @@ pub const DeclState = struct { } }, .Pointer => { - if (ty.isSlice()) { + if (ty.isSlice(mod)) { // Slices are structs: struct { .ptr = *, .len = N } const ptr_bits = target.ptrBitWidth(); const ptr_bytes = @intCast(u8, @divExact(ptr_bits, 8)); diff --git a/src/type.zig b/src/type.zig index 0eff51251d..f05c5e15e8 100644 --- a/src/type.zig +++ b/src/type.zig @@ -229,7 +229,7 @@ pub const Type = struct { .Frame, => false, - .Pointer => !ty.isSlice() and (is_equality_cmp or ty.isCPtr()), + .Pointer => !ty.isSlice(mod) and (is_equality_cmp or ty.isCPtr()), .Optional => { if (!is_equality_cmp) return false; var buf: Payload.ElemType = undefined; @@ -369,209 +369,212 @@ pub const Type = struct { } pub fn ptrInfo(self: Type) Payload.Pointer { - switch (self.tag()) { - .single_const_pointer_to_comptime_int => return .{ .data = .{ - .pointee_type = Type.comptime_int, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .One, - } }, - .const_slice_u8 => return .{ .data = .{ - .pointee_type = Type.u8, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .Slice, - } }, - .const_slice_u8_sentinel_0 => return .{ .data = .{ - .pointee_type = Type.u8, - .sentinel = Value.zero, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .Slice, - } }, - .single_const_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .One, - } }, - .single_mut_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = true, - .@"volatile" = false, - .size = .One, - } }, - .many_const_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .Many, - } }, - .manyptr_const_u8 => return .{ .data = .{ - .pointee_type = Type.u8, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .Many, - } }, - .manyptr_const_u8_sentinel_0 => return .{ .data = .{ - .pointee_type = Type.u8, - .sentinel = Value.zero, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .Many, - } }, - .many_mut_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = true, - .@"volatile" = false, - .size = .Many, - } }, - .manyptr_u8 => return .{ .data = .{ - .pointee_type = Type.u8, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = true, - .@"volatile" = false, - .size = .Many, - } }, - .c_const_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = true, - .mutable = false, - .@"volatile" = false, - .size = .C, - } }, - .c_mut_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = true, - .mutable = true, - .@"volatile" = false, - .size = .C, - } }, - .const_slice => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .Slice, - } }, - .mut_slice => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = true, - .@"volatile" = false, - .size = .Slice, - } }, + switch (self.ip_index) { + .none => switch (self.tag()) { + .single_const_pointer_to_comptime_int => return .{ .data = .{ + .pointee_type = Type.comptime_int, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = false, + .@"volatile" = false, + .size = .One, + } }, + .const_slice_u8 => return .{ .data = .{ + .pointee_type = Type.u8, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = false, + .@"volatile" = false, + .size = .Slice, + } }, + .const_slice_u8_sentinel_0 => return .{ .data = .{ + .pointee_type = Type.u8, + .sentinel = Value.zero, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = false, + .@"volatile" = false, + .size = .Slice, + } }, + .single_const_pointer => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = false, + .@"volatile" = false, + .size = .One, + } }, + .single_mut_pointer => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = true, + .@"volatile" = false, + .size = .One, + } }, + .many_const_pointer => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = false, + .@"volatile" = false, + .size = .Many, + } }, + .manyptr_const_u8 => return .{ .data = .{ + .pointee_type = Type.u8, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = false, + .@"volatile" = false, + .size = .Many, + } }, + .manyptr_const_u8_sentinel_0 => return .{ .data = .{ + .pointee_type = Type.u8, + .sentinel = Value.zero, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = false, + .@"volatile" = false, + .size = .Many, + } }, + .many_mut_pointer => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = true, + .@"volatile" = false, + .size = .Many, + } }, + .manyptr_u8 => return .{ .data = .{ + .pointee_type = Type.u8, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = true, + .@"volatile" = false, + .size = .Many, + } }, + .c_const_pointer => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = true, + .mutable = false, + .@"volatile" = false, + .size = .C, + } }, + .c_mut_pointer => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = true, + .mutable = true, + .@"volatile" = false, + .size = .C, + } }, + .const_slice => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = false, + .@"volatile" = false, + .size = .Slice, + } }, + .mut_slice => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = true, + .@"volatile" = false, + .size = .Slice, + } }, - .pointer => return self.castTag(.pointer).?.*, + .pointer => return self.castTag(.pointer).?.*, - .optional_single_mut_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = true, - .@"volatile" = false, - .size = .One, - } }, - .optional_single_const_pointer => return .{ .data = .{ - .pointee_type = self.castPointer().?.data, - .sentinel = null, - .@"align" = 0, - .@"addrspace" = .generic, - .bit_offset = 0, - .host_size = 0, - .@"allowzero" = false, - .mutable = false, - .@"volatile" = false, - .size = .One, - } }, - .optional => { - var buf: Payload.ElemType = undefined; - const child_type = self.optionalChild(&buf); - return child_type.ptrInfo(); + .optional_single_mut_pointer => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = true, + .@"volatile" = false, + .size = .One, + } }, + .optional_single_const_pointer => return .{ .data = .{ + .pointee_type = self.castPointer().?.data, + .sentinel = null, + .@"align" = 0, + .@"addrspace" = .generic, + .bit_offset = 0, + .host_size = 0, + .@"allowzero" = false, + .mutable = false, + .@"volatile" = false, + .size = .One, + } }, + .optional => { + var buf: Payload.ElemType = undefined; + const child_type = self.optionalChild(&buf); + return child_type.ptrInfo(); + }, + + else => unreachable, }, - - else => unreachable, + else => @panic("TODO"), } } @@ -3712,17 +3715,23 @@ pub const Type = struct { }; } - pub fn isSlice(self: Type) bool { - return switch (self.tag()) { - .const_slice, - .mut_slice, - .const_slice_u8, - .const_slice_u8_sentinel_0, - => true, + pub fn isSlice(ty: Type, mod: *const Module) bool { + return switch (ty.ip_index) { + .none => switch (ty.tag()) { + .const_slice, + .mut_slice, + .const_slice_u8, + .const_slice_u8_sentinel_0, + => true, - .pointer => self.castTag(.pointer).?.data.size == .Slice, + .pointer => ty.castTag(.pointer).?.data.size == .Slice, - else => false, + else => false, + }, + else => switch (mod.intern_pool.indexToKey(ty.ip_index)) { + .ptr_type => |ptr_type| ptr_type.size == .Slice, + else => false, + }, }; } diff --git a/src/value.zig b/src/value.zig index 396aab2012..cbf18c672c 100644 --- a/src/value.zig +++ b/src/value.zig @@ -1144,7 +1144,7 @@ pub const Value = struct { }, }, .Pointer => { - if (ty.isSlice()) return error.IllDefinedMemoryLayout; + if (ty.isSlice(mod)) return error.IllDefinedMemoryLayout; if (val.isDeclRef()) return error.ReinterpretDeclRef; return val.writeToMemory(Type.usize, mod, buffer); }, @@ -1261,7 +1261,7 @@ pub const Value = struct { }, }, .Pointer => { - assert(!ty.isSlice()); // No well defined layout. + assert(!ty.isSlice(mod)); // No well defined layout. if (val.isDeclRef()) return error.ReinterpretDeclRef; return val.writeToPackedMemory(Type.usize, mod, buffer, bit_offset); }, @@ -1381,7 +1381,7 @@ pub const Value = struct { return Value.initPayload(&payload.base); }, .Pointer => { - assert(!ty.isSlice()); // No well defined layout. + assert(!ty.isSlice(mod)); // No well defined layout. return readFromMemory(Type.usize, mod, buffer, arena); }, .Optional => { @@ -1478,7 +1478,7 @@ pub const Value = struct { }, }, .Pointer => { - assert(!ty.isSlice()); // No well defined layout. + assert(!ty.isSlice(mod)); // No well defined layout. return readFromPackedMemory(Type.usize, mod, buffer, bit_offset, arena); }, .Optional => {