mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
InternPool: fix enough crashes to run build-obj on a simple program
This commit is contained in:
parent
9a738c0be5
commit
9afa974183
7 changed files with 228 additions and 115 deletions
|
|
@ -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)) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
50
src/Sema.zig
50
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 {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
140
src/value.zig
140
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,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue