diff --git a/src/InternPool.zig b/src/InternPool.zig index f1bc4e3acc..88f3af6f7f 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -2298,7 +2298,7 @@ pub fn deinit(ip: *InternPool, gpa: Allocator) void { ip.* = undefined; } -pub fn indexToKey(ip: InternPool, index: Index) Key { +pub fn indexToKey(ip: *const InternPool, index: Index) Key { assert(index != .none); const item = ip.items.get(@enumToInt(index)); const data = item.data; @@ -2361,7 +2361,7 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { .type_slice => { const ptr_type_index = @intToEnum(Index, data); - var result = indexToKey(ip, ptr_type_index).ptr_type; + var result = ip.indexToKey(ptr_type_index).ptr_type; result.size = .Slice; return .{ .ptr_type = result }; }, @@ -2454,9 +2454,9 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { .values_map = .none, } }; }, - .type_enum_explicit => indexToKeyEnum(ip, data, .explicit), - .type_enum_nonexhaustive => indexToKeyEnum(ip, data, .nonexhaustive), - .type_function => .{ .func_type = indexToKeyFuncType(ip, data) }, + .type_enum_explicit => ip.indexToKeyEnum(data, .explicit), + .type_enum_nonexhaustive => ip.indexToKeyEnum(data, .nonexhaustive), + .type_function => .{ .func_type = ip.indexToKeyFuncType(data) }, .undef => .{ .undef = @intToEnum(Index, data) }, .runtime_value => { @@ -2591,8 +2591,8 @@ pub fn indexToKey(ip: InternPool, index: Index) Key { .ty = .comptime_int_type, .storage = .{ .i64 = @bitCast(i32, data) }, } }, - .int_positive => indexToKeyBigInt(ip, data, true), - .int_negative => indexToKeyBigInt(ip, data, false), + .int_positive => ip.indexToKeyBigInt(data, true), + .int_negative => ip.indexToKeyBigInt(data, false), .int_small => { const info = ip.extraData(IntSmall, data); return .{ .int = .{ @@ -3430,22 +3430,25 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index { .data = try ip.addExtra(gpa, err), }), - .error_union => |error_union| ip.items.appendAssumeCapacity(switch (error_union.val) { - .err_name => |err_name| .{ - .tag = .error_union_error, - .data = try ip.addExtra(gpa, Key.Error{ - .ty = error_union.ty, - .name = err_name, - }), - }, - .payload => |payload| .{ - .tag = .error_union_payload, - .data = try ip.addExtra(gpa, TypeValue{ - .ty = error_union.ty, - .val = payload, - }), - }, - }), + .error_union => |error_union| { + assert(ip.indexToKey(error_union.ty) == .error_union_type); + ip.items.appendAssumeCapacity(switch (error_union.val) { + .err_name => |err_name| .{ + .tag = .error_union_error, + .data = try ip.addExtra(gpa, Key.Error{ + .ty = error_union.ty, + .name = err_name, + }), + }, + .payload => |payload| .{ + .tag = .error_union_payload, + .data = try ip.addExtra(gpa, TypeValue{ + .ty = error_union.ty, + .val = payload, + }), + }, + }); + }, .enum_literal => |enum_literal| ip.items.appendAssumeCapacity(.{ .tag = .enum_literal, @@ -4191,6 +4194,7 @@ pub fn sliceLen(ip: InternPool, i: Index) Index { /// * ptr <=> ptr /// * null_value => opt /// * payload => opt +/// * error set <=> error set pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Allocator.Error!Index { const old_ty = ip.typeOf(val); if (old_ty == new_ty) return val; @@ -4230,6 +4234,13 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al } }), else => {}, }, + .err => |err| switch (ip.indexToKey(new_ty)) { + .error_set_type, .inferred_error_set_type => return ip.get(gpa, .{ .err = .{ + .ty = new_ty, + .name = err.name, + } }), + else => {}, + }, else => {}, } switch (ip.indexToKey(new_ty)) { diff --git a/src/Liveness/Verify.zig b/src/Liveness/Verify.zig index cbb7f9f143..e8b024eb6f 100644 --- a/src/Liveness/Verify.zig +++ b/src/Liveness/Verify.zig @@ -61,10 +61,10 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { .work_item_id, .work_group_size, .work_group_id, - => try self.verifyInst(inst, .{ .none, .none, .none }), + => try self.verifyInstOperands(inst, .{ .none, .none, .none }), .trap, .unreach => { - try self.verifyInst(inst, .{ .none, .none, .none }); + try self.verifyInstOperands(inst, .{ .none, .none, .none }); // This instruction terminates the function, so everything should be dead if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst}); }, @@ -113,7 +113,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { .c_va_copy, => { const ty_op = data[inst].ty_op; - try self.verifyInst(inst, .{ ty_op.operand, .none, .none }); + try self.verifyInstOperands(inst, .{ ty_op.operand, .none, .none }); }, .is_null, .is_non_null, @@ -149,13 +149,13 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { .c_va_end, => { const un_op = data[inst].un_op; - try self.verifyInst(inst, .{ un_op, .none, .none }); + try self.verifyInstOperands(inst, .{ un_op, .none, .none }); }, .ret, .ret_load, => { const un_op = data[inst].un_op; - try self.verifyInst(inst, .{ un_op, .none, .none }); + try self.verifyInstOperands(inst, .{ un_op, .none, .none }); // This instruction terminates the function, so everything should be dead if (self.live.count() > 0) return invalid("%{}: instructions still alive", .{inst}); }, @@ -164,36 +164,36 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { .wasm_memory_grow, => { const pl_op = data[inst].pl_op; - try self.verifyInst(inst, .{ pl_op.operand, .none, .none }); + try self.verifyInstOperands(inst, .{ pl_op.operand, .none, .none }); }, .prefetch => { const prefetch = data[inst].prefetch; - try self.verifyInst(inst, .{ prefetch.ptr, .none, .none }); + try self.verifyInstOperands(inst, .{ prefetch.ptr, .none, .none }); }, .reduce, .reduce_optimized, => { const reduce = data[inst].reduce; - try self.verifyInst(inst, .{ reduce.operand, .none, .none }); + try self.verifyInstOperands(inst, .{ reduce.operand, .none, .none }); }, .union_init => { const ty_pl = data[inst].ty_pl; const extra = self.air.extraData(Air.UnionInit, ty_pl.payload).data; - try self.verifyInst(inst, .{ extra.init, .none, .none }); + try self.verifyInstOperands(inst, .{ extra.init, .none, .none }); }, .struct_field_ptr, .struct_field_val => { const ty_pl = data[inst].ty_pl; const extra = self.air.extraData(Air.StructField, ty_pl.payload).data; - try self.verifyInst(inst, .{ extra.struct_operand, .none, .none }); + try self.verifyInstOperands(inst, .{ extra.struct_operand, .none, .none }); }, .field_parent_ptr => { const ty_pl = data[inst].ty_pl; const extra = self.air.extraData(Air.FieldParentPtr, ty_pl.payload).data; - try self.verifyInst(inst, .{ extra.field_ptr, .none, .none }); + try self.verifyInstOperands(inst, .{ extra.field_ptr, .none, .none }); }, .atomic_load => { const atomic_load = data[inst].atomic_load; - try self.verifyInst(inst, .{ atomic_load.ptr, .none, .none }); + try self.verifyInstOperands(inst, .{ atomic_load.ptr, .none, .none }); }, // binary @@ -263,7 +263,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { .memcpy, => { const bin_op = data[inst].bin_op; - try self.verifyInst(inst, .{ bin_op.lhs, bin_op.rhs, .none }); + try self.verifyInstOperands(inst, .{ bin_op.lhs, bin_op.rhs, .none }); }, .add_with_overflow, .sub_with_overflow, @@ -277,48 +277,48 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { => { const ty_pl = data[inst].ty_pl; const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; - try self.verifyInst(inst, .{ extra.lhs, extra.rhs, .none }); + try self.verifyInstOperands(inst, .{ extra.lhs, extra.rhs, .none }); }, .shuffle => { const ty_pl = data[inst].ty_pl; const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; - try self.verifyInst(inst, .{ extra.a, extra.b, .none }); + try self.verifyInstOperands(inst, .{ extra.a, extra.b, .none }); }, .cmp_vector, .cmp_vector_optimized, => { const ty_pl = data[inst].ty_pl; const extra = self.air.extraData(Air.VectorCmp, ty_pl.payload).data; - try self.verifyInst(inst, .{ extra.lhs, extra.rhs, .none }); + try self.verifyInstOperands(inst, .{ extra.lhs, extra.rhs, .none }); }, .atomic_rmw => { const pl_op = data[inst].pl_op; const extra = self.air.extraData(Air.AtomicRmw, pl_op.payload).data; - try self.verifyInst(inst, .{ pl_op.operand, extra.operand, .none }); + try self.verifyInstOperands(inst, .{ pl_op.operand, extra.operand, .none }); }, // ternary .select => { const pl_op = data[inst].pl_op; const extra = self.air.extraData(Air.Bin, pl_op.payload).data; - try self.verifyInst(inst, .{ pl_op.operand, extra.lhs, extra.rhs }); + try self.verifyInstOperands(inst, .{ pl_op.operand, extra.lhs, extra.rhs }); }, .mul_add => { const pl_op = data[inst].pl_op; const extra = self.air.extraData(Air.Bin, pl_op.payload).data; - try self.verifyInst(inst, .{ extra.lhs, extra.rhs, pl_op.operand }); + try self.verifyInstOperands(inst, .{ extra.lhs, extra.rhs, pl_op.operand }); }, .vector_store_elem => { const vector_store_elem = data[inst].vector_store_elem; const extra = self.air.extraData(Air.Bin, vector_store_elem.payload).data; - try self.verifyInst(inst, .{ vector_store_elem.vector_ptr, extra.lhs, extra.rhs }); + try self.verifyInstOperands(inst, .{ vector_store_elem.vector_ptr, extra.lhs, extra.rhs }); }, .cmpxchg_strong, .cmpxchg_weak, => { const ty_pl = data[inst].ty_pl; const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data; - try self.verifyInst(inst, .{ extra.ptr, extra.expected_value, extra.new_value }); + try self.verifyInstOperands(inst, .{ extra.ptr, extra.expected_value, extra.new_value }); }, // big tombs @@ -332,7 +332,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { for (elements) |element| { try self.verifyOperand(inst, element, bt.feed()); } - try self.verifyInst(inst, .{ .none, .none, .none }); + try self.verifyInst(inst); }, .call, .call_always_tail, .call_never_tail, .call_never_inline => { const pl_op = data[inst].pl_op; @@ -347,7 +347,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { for (args) |arg| { try self.verifyOperand(inst, arg, bt.feed()); } - try self.verifyInst(inst, .{ .none, .none, .none }); + try self.verifyInst(inst); }, .assembly => { const ty_pl = data[inst].ty_pl; @@ -373,7 +373,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { for (inputs) |input| { try self.verifyOperand(inst, input, bt.feed()); } - try self.verifyInst(inst, .{ .none, .none, .none }); + try self.verifyInst(inst); }, // control flow @@ -397,7 +397,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { for (cond_br_liveness.then_deaths) |death| try self.verifyDeath(inst, death); - try self.verifyInst(inst, .{ .none, .none, .none }); + try self.verifyInst(inst); }, .try_ptr => { const ty_pl = data[inst].ty_pl; @@ -419,7 +419,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { for (cond_br_liveness.then_deaths) |death| try self.verifyDeath(inst, death); - try self.verifyInst(inst, .{ .none, .none, .none }); + try self.verifyInst(inst); }, .br => { const br = data[inst].br; @@ -431,7 +431,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { } else { gop.value_ptr.* = try self.live.clone(self.gpa); } - try self.verifyInst(inst, .{ .none, .none, .none }); + try self.verifyInst(inst); }, .block => { const ty_pl = data[inst].ty_pl; @@ -462,7 +462,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { try self.verifyMatchingLiveness(inst, live); } - try self.verifyInst(inst, .{ .none, .none, .none }); + try self.verifyInstOperands(inst, .{ .none, .none, .none }); }, .loop => { const ty_pl = data[inst].ty_pl; @@ -477,7 +477,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { // The same stuff should be alive after the loop as before it try self.verifyMatchingLiveness(inst, live); - try self.verifyInst(inst, .{ .none, .none, .none }); + try self.verifyInstOperands(inst, .{ .none, .none, .none }); }, .cond_br => { const pl_op = data[inst].pl_op; @@ -500,7 +500,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { for (cond_br_liveness.else_deaths) |death| try self.verifyDeath(inst, death); try self.verifyBody(else_body); - try self.verifyInst(inst, .{ .none, .none, .none }); + try self.verifyInst(inst); }, .switch_br => { const pl_op = data[inst].pl_op; @@ -544,7 +544,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void { try self.verifyBody(else_body); } - try self.verifyInst(inst, .{ .none, .none, .none }); + try self.verifyInst(inst); }, } } @@ -570,7 +570,7 @@ fn verifyOperand(self: *Verify, inst: Air.Inst.Index, op_ref: Air.Inst.Ref, dies } } -fn verifyInst( +fn verifyInstOperands( self: *Verify, inst: Air.Inst.Index, operands: [Liveness.bpi - 1]Air.Inst.Ref, @@ -579,6 +579,10 @@ fn verifyInst( const dies = self.liveness.operandDies(inst, @intCast(Liveness.OperandInt, operand_index)); try self.verifyOperand(inst, operand, dies); } + try self.verifyInst(inst); +} + +fn verifyInst(self: *Verify, inst: Air.Inst.Index) Error!void { if (self.air.instructions.items(.tag)[inst] == .interned) return; if (self.liveness.isUnused(inst)) { assert(!self.live.contains(inst)); diff --git a/src/Sema.zig b/src/Sema.zig index e9c4958918..b0d36c4699 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -16687,7 +16687,6 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai const new_decl_ty = try mod.arrayType(.{ .len = bytes.len, .child = .u8_type, - .sentinel = .zero_u8, }); const new_decl = try anon_decl.finish( new_decl_ty, @@ -16698,7 +16697,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai 0, // default alignment ); break :v try mod.intern(.{ .ptr = .{ - .ty = .slice_const_u8_sentinel_0_type, + .ty = .slice_const_u8_type, .addr = .{ .decl = new_decl }, .len = (try mod.intValue(Type.usize, bytes.len)).toIntern(), } }); @@ -23991,7 +23990,6 @@ fn panicWithMsg( msg_inst: Air.Inst.Ref, ) !void { const mod = sema.mod; - const arena = sema.arena; if (!mod.backendSupportsFeature(.panic_fn)) { _ = try block.addNoOp(.trap); @@ -24001,16 +23999,22 @@ fn panicWithMsg( const unresolved_stack_trace_ty = try sema.getBuiltinType("StackTrace"); const stack_trace_ty = try sema.resolveTypeFields(unresolved_stack_trace_ty); const target = mod.getTarget(); - const ptr_stack_trace_ty = try Type.ptr(arena, mod, .{ - .pointee_type = stack_trace_ty, - .@"addrspace" = target_util.defaultAddressSpace(target, .global_constant), // TODO might need a place that is more dynamic + const ptr_stack_trace_ty = try mod.ptrType(.{ + .elem_type = stack_trace_ty.toIntern(), + .address_space = target_util.defaultAddressSpace(target, .global_constant), // TODO might need a place that is more dynamic }); - const null_stack_trace = try sema.addConstant( - try Type.optional(arena, ptr_stack_trace_ty, mod), - Value.null, - ); - const args: [3]Air.Inst.Ref = .{ msg_inst, null_stack_trace, .null_value }; - try sema.callBuiltin(block, panic_fn, .auto, &args); + const opt_ptr_stack_trace_ty = try mod.optionalType(ptr_stack_trace_ty.toIntern()); + const null_stack_trace = try sema.addConstant(opt_ptr_stack_trace_ty, (try mod.intern(.{ .opt = .{ + .ty = opt_ptr_stack_trace_ty.toIntern(), + .val = .none, + } })).toValue()); + + const opt_usize_ty = try mod.optionalType(.usize_type); + const null_ret_addr = try sema.addConstant(opt_usize_ty, (try mod.intern(.{ .opt = .{ + .ty = opt_usize_ty.toIntern(), + .val = .none, + } })).toValue()); + try sema.callBuiltin(block, panic_fn, .auto, &.{ msg_inst, null_stack_trace, null_ret_addr }); } fn panicUnwrapError( @@ -29395,13 +29399,10 @@ fn refValue(sema: *Sema, block: *Block, ty: Type, val: Value) !Value { fn optRefValue(sema: *Sema, block: *Block, ty: Type, opt_val: ?Value) !Value { const mod = sema.mod; - const val = opt_val orelse return Value.null; - const ptr_val = try sema.refValue(block, ty, val); - const result = try mod.intern(.{ .opt = .{ - .ty = (try mod.optionalType((try mod.singleConstPtrType(ty)).toIntern())).toIntern(), - .val = ptr_val.toIntern(), - } }); - return result.toValue(); + return (try mod.intern(.{ .opt = .{ + .ty = (try mod.optionalType((try mod.singleConstPtrType(Type.anyopaque)).toIntern())).toIntern(), + .val = if (opt_val) |val| (try sema.refValue(block, ty, val)).toIntern() else .none, + } })).toValue(); } fn analyzeDeclRef(sema: *Sema, decl_index: Decl.Index) CompileError!Air.Inst.Ref { @@ -30603,7 +30604,7 @@ fn wrapErrorUnionPayload( if (try sema.resolveMaybeUndefVal(coerced)) |val| { return sema.addConstant(dest_ty, (try mod.intern(.{ .error_union = .{ .ty = dest_ty.toIntern(), - .val = .{ .payload = val.toIntern() }, + .val = .{ .payload = try val.intern(dest_payload_ty, mod) }, } })).toValue()); } try sema.requireRuntimeBlock(block, inst_src, null); @@ -30647,7 +30648,12 @@ fn wrapErrorUnionSet( else => unreachable, }, } - return sema.addConstant(dest_ty, val); + return sema.addConstant(dest_ty, (try mod.intern(.{ .error_union = .{ + .ty = dest_ty.toIntern(), + .val = .{ + .err_name = mod.intern_pool.indexToKey(try val.intern(dest_err_set_ty, mod)).err.name, + }, + } })).toValue()); } try sema.requireRuntimeBlock(block, inst_src, null); @@ -33325,7 +33331,7 @@ fn addIntUnsigned(sema: *Sema, ty: Type, int: u64) CompileError!Air.Inst.Ref { } fn addConstUndef(sema: *Sema, ty: Type) CompileError!Air.Inst.Ref { - return sema.addConstant(ty, Value.undef); + return sema.addConstant(ty, (try sema.mod.intern(.{ .undef = ty.toIntern() })).toValue()); } pub fn addConstant(sema: *Sema, ty: Type, val: Value) SemaError!Air.Inst.Ref { diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 936b1d847a..bbedc1160c 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3267,21 +3267,28 @@ pub const DeclGen = struct { return llvm_ty.constInt(kv.value, .False); }, .error_union => |error_union| { + const err_tv: TypedValue = switch (error_union.val) { + .err_name => |err_name| .{ + .ty = tv.ty.errorUnionSet(mod), + .val = (try mod.intern(.{ .err = .{ + .ty = tv.ty.errorUnionSet(mod).toIntern(), + .name = err_name, + } })).toValue(), + }, + .payload => .{ + .ty = Type.err_int, + .val = try mod.intValue(Type.err_int, 0), + }, + }; const payload_type = tv.ty.errorUnionPayload(mod); - const is_pl = tv.val.errorUnionIsPayload(mod); - if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) { // We use the error type directly as the type. - const err_val = if (!is_pl) tv.val else try mod.intValue(Type.err_int, 0); - return dg.lowerValue(.{ .ty = Type.anyerror, .val = err_val }); + return dg.lowerValue(err_tv); } const payload_align = payload_type.abiAlignment(mod); - const error_align = Type.anyerror.abiAlignment(mod); - const llvm_error_value = try dg.lowerValue(.{ - .ty = Type.anyerror, - .val = if (is_pl) try mod.intValue(Type.err_int, 0) else tv.val, - }); + const error_align = err_tv.ty.abiAlignment(mod); + const llvm_error_value = try dg.lowerValue(err_tv); const llvm_payload_value = try dg.lowerValue(.{ .ty = payload_type, .val = switch (error_union.val) { diff --git a/src/print_air.zig b/src/print_air.zig index 204f5ddeb9..800fbc43c2 100644 --- a/src/print_air.zig +++ b/src/print_air.zig @@ -703,7 +703,7 @@ const Writer = struct { const pl_op = w.air.instructions.items(.data)[inst].pl_op; try w.writeOperand(s, inst, 0, pl_op.operand); const name = w.air.nullTerminatedString(pl_op.payload); - try s.print(", {s}", .{name}); + try s.print(", \"{}\"", .{std.zig.fmtEscapes(name)}); } fn writeCall(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void { diff --git a/src/value.zig b/src/value.zig index 498b7d3339..bf201aceaf 100644 --- a/src/value.zig +++ b/src/value.zig @@ -347,6 +347,43 @@ pub const Value = struct { pub fn intern(val: Value, ty: Type, mod: *Module) Allocator.Error!InternPool.Index { if (val.ip_index != .none) return mod.intern_pool.getCoerced(mod.gpa, val.toIntern(), ty.toIntern()); switch (val.tag()) { + .eu_payload => { + const pl = val.castTag(.eu_payload).?.data; + return mod.intern(.{ .error_union = .{ + .ty = ty.toIntern(), + .val = .{ .payload = try pl.intern(ty.errorUnionPayload(mod), mod) }, + } }); + }, + .opt_payload => { + const pl = val.castTag(.opt_payload).?.data; + return mod.intern(.{ .opt = .{ + .ty = ty.toIntern(), + .val = try pl.intern(ty.optionalChild(mod), mod), + } }); + }, + .slice => { + const pl = val.castTag(.slice).?.data; + const ptr = try pl.ptr.intern(ty.optionalChild(mod), mod); + var ptr_key = mod.intern_pool.indexToKey(ptr).ptr; + assert(ptr_key.len == .none); + ptr_key.ty = ty.toIntern(); + ptr_key.len = try pl.len.intern(Type.usize, mod); + return mod.intern(.{ .ptr = ptr_key }); + }, + .bytes => { + const pl = val.castTag(.bytes).?.data; + return mod.intern(.{ .aggregate = .{ + .ty = ty.toIntern(), + .storage = .{ .bytes = pl }, + } }); + }, + .repeated => { + const pl = val.castTag(.repeated).?.data; + return mod.intern(.{ .aggregate = .{ + .ty = ty.toIntern(), + .storage = .{ .repeated_elem = try pl.intern(ty.childType(mod), mod) }, + } }); + }, .aggregate => { const old_elems = val.castTag(.aggregate).?.data; const new_elems = try mod.gpa.alloc(InternPool.Index, old_elems.len); @@ -372,24 +409,74 @@ pub const Value = struct { .val = try pl.val.intern(ty.unionFieldType(pl.tag, mod), mod), } }); }, - else => unreachable, } } pub fn unintern(val: Value, arena: Allocator, mod: *Module) Allocator.Error!Value { - if (val.ip_index == .none) return val; - switch (mod.intern_pool.indexToKey(val.toIntern())) { + return if (val.ip_index == .none) val else switch (mod.intern_pool.indexToKey(val.toIntern())) { + .int_type, + .ptr_type, + .array_type, + .vector_type, + .opt_type, + .anyframe_type, + .error_union_type, + .simple_type, + .struct_type, + .anon_struct_type, + .union_type, + .opaque_type, + .enum_type, + .func_type, + .error_set_type, + .inferred_error_set_type, + + .undef, + .runtime_value, + .simple_value, + .variable, + .extern_func, + .func, + .int, + .err, + .enum_literal, + .enum_tag, + .float, + => val, + + .error_union => |error_union| switch (error_union.val) { + .err_name => val, + .payload => |payload| Tag.eu_payload.create(arena, payload.toValue()), + }, + + .ptr => |ptr| switch (ptr.len) { + .none => val, + else => |len| Tag.slice.create(arena, .{ + .ptr = val.slicePtr(mod), + .len = len.toValue(), + }), + }, + + .opt => |opt| switch (opt.val) { + .none => val, + else => |payload| Tag.opt_payload.create(arena, payload.toValue()), + }, + .aggregate => |aggregate| switch (aggregate.storage) { - .bytes => |bytes| return Tag.bytes.create(arena, try arena.dupe(u8, bytes)), + .bytes => |bytes| Tag.bytes.create(arena, try arena.dupe(u8, bytes)), .elems => |old_elems| { const new_elems = try arena.alloc(Value, old_elems.len); for (new_elems, old_elems) |*new_elem, old_elem| new_elem.* = old_elem.toValue(); return Tag.aggregate.create(arena, new_elems); }, - .repeated_elem => |elem| return Tag.repeated.create(arena, elem.toValue()), + .repeated_elem => |elem| Tag.repeated.create(arena, elem.toValue()), }, - else => return val, - } + + .un => |un| Tag.@"union".create(arena, .{ + .tag = un.tag.toValue(), + .val = un.val.toValue(), + }), + }; } pub fn toIntern(val: Value) InternPool.Index { @@ -1896,7 +1983,7 @@ pub const Value = struct { /// Returns true if a Value is backed by a variable pub fn isVariable(val: Value, mod: *Module) bool { - return switch (mod.intern_pool.indexToKey(val.toIntern())) { + return val.ip_index != .none and switch (mod.intern_pool.indexToKey(val.toIntern())) { .variable => true, .ptr => |ptr| switch (ptr.addr) { .decl => |decl_index| { @@ -1919,28 +2006,25 @@ pub const Value = struct { } pub fn isPtrToThreadLocal(val: Value, mod: *Module) bool { - return switch (val.ip_index) { - .none => false, - else => switch (mod.intern_pool.indexToKey(val.toIntern())) { - .variable => |variable| variable.is_threadlocal, - .ptr => |ptr| switch (ptr.addr) { - .decl => |decl_index| { - const decl = mod.declPtr(decl_index); - assert(decl.has_tv); - return decl.val.isPtrToThreadLocal(mod); - }, - .mut_decl => |mut_decl| { - const decl = mod.declPtr(mut_decl.decl); - assert(decl.has_tv); - return decl.val.isPtrToThreadLocal(mod); - }, - .int => false, - .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isPtrToThreadLocal(mod), - .comptime_field => |comptime_field| comptime_field.toValue().isPtrToThreadLocal(mod), - .elem, .field => |base_index| base_index.base.toValue().isPtrToThreadLocal(mod), + return val.ip_index != .none and switch (mod.intern_pool.indexToKey(val.toIntern())) { + .variable => |variable| variable.is_threadlocal, + .ptr => |ptr| switch (ptr.addr) { + .decl => |decl_index| { + const decl = mod.declPtr(decl_index); + assert(decl.has_tv); + return decl.val.isPtrToThreadLocal(mod); }, - else => false, + .mut_decl => |mut_decl| { + const decl = mod.declPtr(mut_decl.decl); + assert(decl.has_tv); + return decl.val.isPtrToThreadLocal(mod); + }, + .int => false, + .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isPtrToThreadLocal(mod), + .comptime_field => |comptime_field| comptime_field.toValue().isPtrToThreadLocal(mod), + .elem, .field => |base_index| base_index.base.toValue().isPtrToThreadLocal(mod), }, + else => false, }; } diff --git a/tools/lldb_pretty_printers.py b/tools/lldb_pretty_printers.py index 36e497afb9..7408570830 100644 --- a/tools/lldb_pretty_printers.py +++ b/tools/lldb_pretty_printers.py @@ -681,6 +681,7 @@ def __lldb_init_module(debugger, _=None): add(debugger, category='zig.stage2', regex=True, type=MultiArrayList_Entry('Air\\.Inst'), identifier='TagAndPayload', synth=True, inline_children=True, summary=True) add(debugger, category='zig.stage2', regex=True, type='^Air\\.Inst\\.Data\\.Data__struct_[1-9][0-9]*$', inline_children=True, summary=True) add(debugger, category='zig.stage2', type='Module.Decl::Module.Decl.Index', synth=True) + add(debugger, category='zig.stage2', type='Module.LazySrcLoc', identifier='zig_TaggedUnion', synth=True) add(debugger, category='zig.stage2', type='InternPool.Index', synth=True) add(debugger, category='zig.stage2', type='InternPool.Key', identifier='zig_TaggedUnion', synth=True) add(debugger, category='zig.stage2', type='InternPool.Key.Int.Storage', identifier='zig_TaggedUnion', synth=True)