diff --git a/src/InternPool.zig b/src/InternPool.zig index 5a7500cafd..837dc96daf 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -2584,9 +2584,9 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { .extern_func => @panic("TODO"), - .ptr => |ptr| switch (ip.items.items(.tag)[@enumToInt(ptr.ty)]) { - .type_pointer => { - assert(ptr.len == .none); + .ptr => |ptr| switch (ptr.len) { + .none => { + assert(ip.indexToKey(ptr.ty).ptr_type.size != .Slice); switch (ptr.addr) { .@"var" => |@"var"| ip.items.appendAssumeCapacity(.{ .tag = .ptr_var, @@ -2626,11 +2626,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { }), } }, - .type_slice => { - assert(ptr.len != .none); + else => { + assert(ip.indexToKey(ptr.ty).ptr_type.size == .Slice); var new_key = key; - new_key.ptr.ty = @intToEnum(Index, ip.items.items(.data)[@enumToInt(ptr.ty)]); + new_key.ptr.ty = ip.slicePtrType(ptr.ty); new_key.ptr.len = .none; + assert(ip.indexToKey(new_key.ptr.ty).ptr_type.size == .Many); const ptr_index = try get(ip, gpa, new_key); try ip.items.ensureUnusedCapacity(gpa, 1); ip.items.appendAssumeCapacity(.{ @@ -2641,7 +2642,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { }), }); }, - else => unreachable, }, .opt => |opt| { @@ -3465,10 +3465,12 @@ pub fn sliceLen(ip: InternPool, i: Index) Index { /// Given an existing value, returns the same value but with the supplied type. /// Only some combinations are allowed: +/// * identity coercion /// * int <=> int /// * int <=> enum /// * ptr <=> ptr pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index { + if (ip.typeOf(val) == new_ty) return val; switch (ip.indexToKey(val)) { .int => |int| switch (ip.indexToKey(new_ty)) { .enum_type => return ip.get(gpa, .{ .enum_tag = .{ diff --git a/src/Sema.zig b/src/Sema.zig index 14383d107e..57a88ad782 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -7836,7 +7836,7 @@ fn resolveGenericInstantiationType( const arg_val = (child_sema.resolveMaybeUndefValAllowVariables(arg) catch unreachable).?; child_sema.comptime_args[arg_i] = .{ .ty = arg_ty, - .val = try arg_val.copy(new_decl_arena_allocator), + .val = (try arg_val.intern(arg_ty, mod)).toValue(), }; } else { child_sema.comptime_args[arg_i] = .{ @@ -16537,7 +16537,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i}); const new_decl = try anon_decl.finish( try Type.array(anon_decl.arena(), bytes.len, Value.zero_u8, Type.u8, mod), - try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]), + try Value.Tag.bytes.create(anon_decl.arena(), bytes.ptr[0 .. bytes.len + 1]), 0, // default alignment ); break :v try Value.Tag.slice.create(fields_anon_decl.arena(), .{ diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 12d6a5752d..0f7a61f1bf 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3357,7 +3357,7 @@ pub const DeclGen = struct { }), }, else => switch (mod.intern_pool.indexToKey(tv.val.ip_index)) { - .int => |int| return lowerIntAsPtr(dg, int), + .int => |int| return dg.lowerIntAsPtr(int), .ptr => |ptr| { const ptr_val = switch (ptr.addr) { .@"var" => |@"var"| ptr: { @@ -3376,7 +3376,7 @@ pub const DeclGen = struct { }, .decl => |decl| try lowerDeclRefValue(dg, tv, decl), .mut_decl => |mut_decl| try lowerDeclRefValue(dg, tv, mut_decl.decl), - .int => |int| lowerIntAsPtr(dg, mod.intern_pool.indexToKey(int).int), + .int => |int| dg.lowerIntAsPtr(mod.intern_pool.indexToKey(int).int), }; switch (ptr.len) { .none => return ptr_val, @@ -4084,8 +4084,14 @@ pub const DeclGen = struct { fn lowerParentPtr(dg: *DeclGen, ptr_val: Value, byte_aligned: bool) Error!*llvm.Value { const mod = dg.module; const target = mod.getTarget(); - if (ptr_val.ip_index != .none) switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) { - .int => |int| return lowerIntAsPtr(dg, int), + if (ptr_val.ip_index != .none) return switch (mod.intern_pool.indexToKey(ptr_val.ip_index)) { + .int => |int| dg.lowerIntAsPtr(int), + .ptr => |ptr| switch (ptr.addr) { + .@"var" => |@"var"| dg.lowerParentPtrDecl(ptr_val, @"var".owner_decl), + .decl => |decl| dg.lowerParentPtrDecl(ptr_val, decl), + .mut_decl => |mut_decl| dg.lowerParentPtrDecl(ptr_val, mut_decl.decl), + .int => |int| dg.lowerIntAsPtr(mod.intern_pool.indexToKey(int).int), + }, else => unreachable, }; switch (ptr_val.tag()) { diff --git a/src/value.zig b/src/value.zig index 3e5e98db17..d17e14d146 100644 --- a/src/value.zig +++ b/src/value.zig @@ -603,7 +603,7 @@ pub const Value = struct { } pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index { - if (val.ip_index != .none) return val.ip_index; + if (val.ip_index != .none) return mod.intern_pool.getCoerced(mod.gpa, val.ip_index, ty.ip_index); switch (val.tag()) { .slice => { const pl = val.castTag(.slice).?.data; @@ -2769,9 +2769,18 @@ pub const Value = struct { mod: *Module, ) Allocator.Error!Value { const elem_ty = ty.elemType2(mod); - const ptr_val = switch (val.tag()) { - .slice => val.castTag(.slice).?.data.ptr, - else => val, + const ptr_val = switch (val.ip_index) { + .none => switch (val.tag()) { + .slice => val.castTag(.slice).?.data.ptr, + else => val, + }, + else => switch (mod.intern_pool.indexToKey(val.ip_index)) { + .ptr => |ptr| switch (ptr.len) { + .none => val, + else => val.slicePtr(mod), + }, + else => val, + }, }; if (ptr_val.ip_index == .none and ptr_val.tag() == .elem_ptr) {