mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
behavior: fix more compiler crashes
This commit is contained in:
parent
3064d2aa7b
commit
3269256965
9 changed files with 309 additions and 205 deletions
|
|
@ -1416,7 +1416,12 @@ pub const Index = enum(u32) {
|
|||
only_possible_value: DataIsIndex,
|
||||
union_value: struct { data: *Key.Union },
|
||||
bytes: struct { data: *Bytes },
|
||||
aggregate: struct { data: *Aggregate },
|
||||
aggregate: struct {
|
||||
const @"data.ty.data.len orelse data.ty.data.fields_len" = opaque {};
|
||||
data: *Aggregate,
|
||||
@"trailing.element_values.len": *@"data.ty.data.len orelse data.ty.data.fields_len",
|
||||
trailing: struct { element_values: []Index },
|
||||
},
|
||||
repeated: struct { data: *Repeated },
|
||||
|
||||
memoized_decl: struct { data: *Key.MemoizedDecl },
|
||||
|
|
@ -4437,7 +4442,7 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
|
|||
.Slice => try ip.get(gpa, .{ .undef = .usize_type }),
|
||||
},
|
||||
} }),
|
||||
else => try ip.getCoerced(gpa, opt.val, new_ty),
|
||||
else => |payload| try ip.getCoerced(gpa, payload, new_ty),
|
||||
},
|
||||
.err => |err| if (ip.isErrorSetType(new_ty))
|
||||
return ip.get(gpa, .{ .err = .{
|
||||
|
|
@ -4622,7 +4627,7 @@ pub fn isErrorUnionType(ip: InternPool, ty: Index) bool {
|
|||
|
||||
pub fn isAggregateType(ip: InternPool, ty: Index) bool {
|
||||
return switch (ip.indexToKey(ty)) {
|
||||
.array_wype, .vector_type, .anon_struct_type, .struct_type => true,
|
||||
.array_type, .vector_type, .anon_struct_type, .struct_type => true,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6678,14 +6678,14 @@ pub fn optionalType(mod: *Module, child_type: InternPool.Index) Allocator.Error!
|
|||
|
||||
pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type {
|
||||
var canon_info = info;
|
||||
const have_elem_layout = info.elem_type.toType().layoutIsResolved(mod);
|
||||
|
||||
// Canonicalize non-zero alignment. If it matches the ABI alignment of the pointee
|
||||
// type, we change it to 0 here. If this causes an assertion trip because the
|
||||
// pointee type needs to be resolved more, that needs to be done before calling
|
||||
// this ptr() function.
|
||||
if (info.alignment.toByteUnitsOptional()) |info_align| {
|
||||
const elem_align = info.elem_type.toType().abiAlignment(mod);
|
||||
if (info.elem_type.toType().layoutIsResolved(mod) and info_align == elem_align) {
|
||||
if (have_elem_layout and info_align == info.elem_type.toType().abiAlignment(mod)) {
|
||||
canon_info.alignment = .none;
|
||||
}
|
||||
}
|
||||
|
|
@ -6694,7 +6694,7 @@ pub fn ptrType(mod: *Module, info: InternPool.Key.PtrType) Allocator.Error!Type
|
|||
// Canonicalize host_size. If it matches the bit size of the pointee type,
|
||||
// we change it to 0 here. If this causes an assertion trip, the pointee type
|
||||
// needs to be resolved before calling this ptr() function.
|
||||
.none => if (info.host_size != 0) {
|
||||
.none => if (have_elem_layout and info.host_size != 0) {
|
||||
const elem_bit_size = info.elem_type.toType().bitSize(mod);
|
||||
assert(info.bit_offset + elem_bit_size <= info.host_size * 8);
|
||||
if (info.host_size * 8 == elem_bit_size) {
|
||||
|
|
@ -6782,21 +6782,7 @@ pub fn errorSetFromUnsortedNames(
|
|||
|
||||
/// Supports optionals in addition to pointers.
|
||||
pub fn ptrIntValue(mod: *Module, ty: Type, x: u64) Allocator.Error!Value {
|
||||
if (ty.isPtrLikeOptional(mod)) {
|
||||
const i = try intern(mod, .{ .opt = .{
|
||||
.ty = ty.toIntern(),
|
||||
.val = try intern(mod, .{ .ptr = .{
|
||||
.ty = ty.childType(mod).toIntern(),
|
||||
.addr = .{ .int = try intern(mod, .{ .int = .{
|
||||
.ty = .usize_type,
|
||||
.storage = .{ .u64 = x },
|
||||
} }) },
|
||||
} }),
|
||||
} });
|
||||
return i.toValue();
|
||||
} else {
|
||||
return ptrIntValue_ptronly(mod, ty, x);
|
||||
}
|
||||
return mod.getCoerced(try mod.intValue_u64(Type.usize, x), ty);
|
||||
}
|
||||
|
||||
/// Supports only pointers. See `ptrIntValue` for pointer-like optional support.
|
||||
|
|
@ -6804,10 +6790,7 @@ pub fn ptrIntValue_ptronly(mod: *Module, ty: Type, x: u64) Allocator.Error!Value
|
|||
assert(ty.zigTypeTag(mod) == .Pointer);
|
||||
const i = try intern(mod, .{ .ptr = .{
|
||||
.ty = ty.toIntern(),
|
||||
.addr = .{ .int = try intern(mod, .{ .int = .{
|
||||
.ty = .usize_type,
|
||||
.storage = .{ .u64 = x },
|
||||
} }) },
|
||||
.addr = .{ .int = try mod.intValue_u64(Type.usize, x) },
|
||||
} });
|
||||
return i.toValue();
|
||||
}
|
||||
|
|
@ -6954,7 +6937,7 @@ pub fn intBitsForValue(mod: *Module, val: Value, sign: bool) u16 {
|
|||
const key = mod.intern_pool.indexToKey(val.toIntern());
|
||||
switch (key.int.storage) {
|
||||
.i64 => |x| {
|
||||
if (std.math.cast(u64, x)) |casted| return Type.smallestUnsignedBits(casted);
|
||||
if (std.math.cast(u64, x)) |casted| return Type.smallestUnsignedBits(casted) + @boolToInt(sign);
|
||||
assert(sign);
|
||||
// Protect against overflow in the following negation.
|
||||
if (x == std.math.minInt(i64)) return 64;
|
||||
|
|
|
|||
156
src/Sema.zig
156
src/Sema.zig
|
|
@ -9510,7 +9510,10 @@ fn zirPtrToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
|||
return sema.fail(block, ptr_src, "expected pointer, found '{}'", .{ptr_ty.fmt(sema.mod)});
|
||||
}
|
||||
if (try sema.resolveMaybeUndefValIntable(ptr)) |ptr_val| {
|
||||
return sema.addConstant(Type.usize, try mod.getCoerced(ptr_val, Type.usize));
|
||||
return sema.addConstant(
|
||||
Type.usize,
|
||||
try mod.intValue(Type.usize, (try ptr_val.getUnsignedIntAdvanced(mod, sema)).?),
|
||||
);
|
||||
}
|
||||
try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src);
|
||||
return block.addUnOp(.ptrtoint, ptr);
|
||||
|
|
@ -27879,7 +27882,7 @@ fn beginComptimePtrMutation(
|
|||
.undef => try mod.intern(.{ .undef = payload_ty.toIntern() }),
|
||||
.opt => |opt| switch (opt.val) {
|
||||
.none => try mod.intern(.{ .undef = payload_ty.toIntern() }),
|
||||
else => opt.val,
|
||||
else => |payload| payload,
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
|
|
@ -28438,7 +28441,7 @@ fn beginComptimePtrLoad(
|
|||
},
|
||||
.opt => |opt| switch (opt.val) {
|
||||
.none => return sema.fail(block, src, "attempt to use null value", .{}),
|
||||
else => opt.val,
|
||||
else => |payload| payload,
|
||||
},
|
||||
else => unreachable,
|
||||
}.toValue(),
|
||||
|
|
@ -28591,7 +28594,7 @@ fn beginComptimePtrLoad(
|
|||
},
|
||||
.opt => |opt| switch (opt.val) {
|
||||
.none => return sema.fail(block, src, "attempt to use null value", .{}),
|
||||
else => try sema.beginComptimePtrLoad(block, src, opt.val.toValue(), null),
|
||||
else => |payload| try sema.beginComptimePtrLoad(block, src, payload.toValue(), null),
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
|
|
@ -28931,8 +28934,30 @@ fn coerceAnonStructToUnion(
|
|||
) !Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const inst_ty = sema.typeOf(inst);
|
||||
const field_count = inst_ty.structFieldCount(mod);
|
||||
if (field_count != 1) {
|
||||
const field_info: union(enum) {
|
||||
name: []const u8,
|
||||
count: usize,
|
||||
} = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
|
||||
.anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len == 1)
|
||||
.{ .name = mod.intern_pool.stringToSlice(anon_struct_type.names[0]) }
|
||||
else
|
||||
.{ .count = anon_struct_type.names.len },
|
||||
.struct_type => |struct_type| name: {
|
||||
const field_names = mod.structPtrUnwrap(struct_type.index).?.fields.keys();
|
||||
break :name if (field_names.len == 1)
|
||||
.{ .name = field_names[0] }
|
||||
else
|
||||
.{ .count = field_names.len };
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
switch (field_info) {
|
||||
.name => |field_name| {
|
||||
const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty);
|
||||
return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src);
|
||||
},
|
||||
.count => |field_count| {
|
||||
assert(field_count != 1);
|
||||
const msg = msg: {
|
||||
const msg = if (field_count > 1) try sema.errMsg(
|
||||
block,
|
||||
|
|
@ -28954,12 +28979,8 @@ fn coerceAnonStructToUnion(
|
|||
break :msg msg;
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
},
|
||||
}
|
||||
|
||||
const anon_struct = mod.intern_pool.indexToKey(inst_ty.toIntern()).anon_struct_type;
|
||||
const field_name = mod.intern_pool.stringToSlice(anon_struct.names[0]);
|
||||
const init = try sema.structFieldVal(block, inst_src, inst, field_name, inst_src, inst_ty);
|
||||
return sema.unionInit(block, init, inst_src, union_ty, union_ty_src, field_name, inst_src);
|
||||
}
|
||||
|
||||
fn coerceAnonStructToUnionPtrs(
|
||||
|
|
@ -29193,16 +29214,27 @@ fn coerceTupleToStruct(
|
|||
@memset(field_refs, .none);
|
||||
|
||||
const inst_ty = sema.typeOf(inst);
|
||||
const anon_struct = mod.intern_pool.indexToKey(inst_ty.toIntern()).anon_struct_type;
|
||||
var runtime_src: ?LazySrcLoc = null;
|
||||
for (0..anon_struct.types.len) |field_index_usize| {
|
||||
const field_count = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
|
||||
.anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
|
||||
.struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj|
|
||||
struct_obj.fields.count()
|
||||
else
|
||||
0,
|
||||
else => unreachable,
|
||||
};
|
||||
for (0..field_count) |field_index_usize| {
|
||||
const field_i = @intCast(u32, field_index_usize);
|
||||
const field_src = inst_src; // TODO better source location
|
||||
const field_name = if (anon_struct.names.len != 0)
|
||||
// https://github.com/ziglang/zig/issues/15709
|
||||
@as([]const u8, mod.intern_pool.stringToSlice(anon_struct.names[field_i]))
|
||||
const field_name: []const u8 = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
|
||||
.anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
|
||||
mod.intern_pool.stringToSlice(anon_struct_type.names[field_i])
|
||||
else
|
||||
try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});
|
||||
try std.fmt.allocPrint(sema.arena, "{d}", .{field_i}),
|
||||
.struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.keys()[field_i],
|
||||
else => unreachable,
|
||||
};
|
||||
const field_index = try sema.structFieldIndex(block, struct_ty, field_name, field_src);
|
||||
const field = fields.values()[field_index];
|
||||
const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
|
||||
|
|
@ -29281,40 +29313,72 @@ fn coerceTupleToTuple(
|
|||
inst_src: LazySrcLoc,
|
||||
) !Air.Inst.Ref {
|
||||
const mod = sema.mod;
|
||||
const dest_tuple = mod.intern_pool.indexToKey(tuple_ty.toIntern()).anon_struct_type;
|
||||
const field_vals = try sema.arena.alloc(InternPool.Index, dest_tuple.types.len);
|
||||
const dest_field_count = switch (mod.intern_pool.indexToKey(tuple_ty.toIntern())) {
|
||||
.anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
|
||||
.struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj|
|
||||
struct_obj.fields.count()
|
||||
else
|
||||
0,
|
||||
else => unreachable,
|
||||
};
|
||||
const field_vals = try sema.arena.alloc(InternPool.Index, dest_field_count);
|
||||
const field_refs = try sema.arena.alloc(Air.Inst.Ref, field_vals.len);
|
||||
@memset(field_refs, .none);
|
||||
|
||||
const inst_ty = sema.typeOf(inst);
|
||||
const src_tuple = mod.intern_pool.indexToKey(inst_ty.toIntern()).anon_struct_type;
|
||||
if (src_tuple.types.len > dest_tuple.types.len) return error.NotCoercible;
|
||||
const src_field_count = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
|
||||
.anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
|
||||
.struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj|
|
||||
struct_obj.fields.count()
|
||||
else
|
||||
0,
|
||||
else => unreachable,
|
||||
};
|
||||
if (src_field_count > dest_field_count) return error.NotCoercible;
|
||||
|
||||
var runtime_src: ?LazySrcLoc = null;
|
||||
for (dest_tuple.types, dest_tuple.values, 0..) |field_ty, default_val, field_index_usize| {
|
||||
for (0..dest_field_count) |field_index_usize| {
|
||||
const field_i = @intCast(u32, field_index_usize);
|
||||
const field_src = inst_src; // TODO better source location
|
||||
const field_name = if (src_tuple.names.len != 0)
|
||||
// https://github.com/ziglang/zig/issues/15709
|
||||
@as([]const u8, mod.intern_pool.stringToSlice(src_tuple.names[field_i]))
|
||||
const field_name: []const u8 = switch (mod.intern_pool.indexToKey(inst_ty.toIntern())) {
|
||||
.anon_struct_type => |anon_struct_type| if (anon_struct_type.names.len > 0)
|
||||
mod.intern_pool.stringToSlice(anon_struct_type.names[field_i])
|
||||
else
|
||||
try std.fmt.allocPrint(sema.arena, "{d}", .{field_i});
|
||||
try std.fmt.allocPrint(sema.arena, "{d}", .{field_i}),
|
||||
.struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.keys()[field_i],
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
if (mem.eql(u8, field_name, "len")) {
|
||||
return sema.fail(block, field_src, "cannot assign to 'len' field of tuple", .{});
|
||||
}
|
||||
|
||||
const field_ty = switch (mod.intern_pool.indexToKey(tuple_ty.toIntern())) {
|
||||
.anon_struct_type => |anon_struct_type| anon_struct_type.types[field_index_usize].toType(),
|
||||
.struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[field_index_usize].ty,
|
||||
else => unreachable,
|
||||
};
|
||||
const default_val = switch (mod.intern_pool.indexToKey(tuple_ty.toIntern())) {
|
||||
.anon_struct_type => |anon_struct_type| anon_struct_type.values[field_index_usize],
|
||||
.struct_type => |struct_type| switch (mod.structPtrUnwrap(struct_type.index).?.fields.values()[field_index_usize].default_val.toIntern()) {
|
||||
.unreachable_value => .none,
|
||||
else => |default_val| default_val,
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
const field_index = try sema.tupleFieldIndex(block, tuple_ty, field_name, field_src);
|
||||
|
||||
const elem_ref = try sema.tupleField(block, inst_src, inst, field_src, field_i);
|
||||
const coerced = try sema.coerce(block, field_ty.toType(), elem_ref, field_src);
|
||||
const coerced = try sema.coerce(block, field_ty, elem_ref, field_src);
|
||||
field_refs[field_index] = coerced;
|
||||
if (default_val != .none) {
|
||||
const init_val = (try sema.resolveMaybeUndefVal(coerced)) orelse {
|
||||
return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
|
||||
};
|
||||
|
||||
if (!init_val.eql(default_val.toValue(), field_ty.toType(), sema.mod)) {
|
||||
if (!init_val.eql(default_val.toValue(), field_ty, sema.mod)) {
|
||||
return sema.failWithInvalidComptimeFieldStore(block, field_src, inst_ty, field_i);
|
||||
}
|
||||
}
|
||||
|
|
@ -29331,14 +29395,18 @@ fn coerceTupleToTuple(
|
|||
var root_msg: ?*Module.ErrorMsg = null;
|
||||
errdefer if (root_msg) |msg| msg.destroy(sema.gpa);
|
||||
|
||||
for (
|
||||
dest_tuple.types,
|
||||
dest_tuple.values,
|
||||
field_refs,
|
||||
0..,
|
||||
) |field_ty, default_val, *field_ref, i| {
|
||||
for (field_refs, 0..) |*field_ref, i| {
|
||||
if (field_ref.* != .none) continue;
|
||||
|
||||
const default_val = switch (mod.intern_pool.indexToKey(tuple_ty.toIntern())) {
|
||||
.anon_struct_type => |anon_struct_type| anon_struct_type.values[i],
|
||||
.struct_type => |struct_type| switch (mod.structPtrUnwrap(struct_type.index).?.fields.values()[i].default_val.toIntern()) {
|
||||
.unreachable_value => .none,
|
||||
else => |default_val| default_val,
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
const field_src = inst_src; // TODO better source location
|
||||
if (default_val == .none) {
|
||||
if (tuple_ty.isTuple(mod)) {
|
||||
|
|
@ -29362,7 +29430,12 @@ fn coerceTupleToTuple(
|
|||
if (runtime_src == null) {
|
||||
field_vals[i] = default_val;
|
||||
} else {
|
||||
field_ref.* = try sema.addConstant(field_ty.toType(), default_val.toValue());
|
||||
const field_ty = switch (mod.intern_pool.indexToKey(tuple_ty.toIntern())) {
|
||||
.anon_struct_type => |anon_struct_type| anon_struct_type.types[i].toType(),
|
||||
.struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.values()[i].ty,
|
||||
else => unreachable,
|
||||
};
|
||||
field_ref.* = try sema.addConstant(field_ty, default_val.toValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -33959,11 +34032,20 @@ fn anonStructFieldIndex(
|
|||
field_src: LazySrcLoc,
|
||||
) !u32 {
|
||||
const mod = sema.mod;
|
||||
const anon_struct = mod.intern_pool.indexToKey(struct_ty.toIntern()).anon_struct_type;
|
||||
for (anon_struct.names, 0..) |name, i| {
|
||||
switch (mod.intern_pool.indexToKey(struct_ty.toIntern())) {
|
||||
.anon_struct_type => |anon_struct_type| for (anon_struct_type.names, 0..) |name, i| {
|
||||
if (mem.eql(u8, mod.intern_pool.stringToSlice(name), field_name)) {
|
||||
return @intCast(u32, i);
|
||||
}
|
||||
},
|
||||
.struct_type => |struct_type| if (mod.structPtrUnwrap(struct_type.index)) |struct_obj| {
|
||||
for (struct_obj.fields.keys(), 0..) |name, i| {
|
||||
if (mem.eql(u8, name, field_name)) {
|
||||
return @intCast(u32, i);
|
||||
}
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
return sema.fail(block, field_src, "no field named '{s}' in anonymous struct '{}'", .{
|
||||
field_name, struct_ty.fmt(sema.mod),
|
||||
|
|
@ -34006,6 +34088,10 @@ fn intAddScalar(sema: *Sema, lhs: Value, rhs: Value, scalar_ty: Type) !Value {
|
|||
);
|
||||
var result_bigint = std.math.big.int.Mutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||
result_bigint.add(lhs_bigint, rhs_bigint);
|
||||
if (scalar_ty.toIntern() != .comptime_int_type) {
|
||||
const int_info = scalar_ty.intInfo(mod);
|
||||
result_bigint.truncate(result_bigint.toConst(), int_info.signedness, int_info.bits);
|
||||
}
|
||||
return mod.intValue_big(scalar_ty, result_bigint.toConst());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -254,8 +254,8 @@ pub fn print(
|
|||
.ptr => return writer.writeAll("(ptr)"),
|
||||
.opt => |opt| switch (opt.val) {
|
||||
.none => return writer.writeAll("null"),
|
||||
else => {
|
||||
val = opt.val.toValue();
|
||||
else => |payload| {
|
||||
val = payload.toValue();
|
||||
ty = ty.optionalChild(mod);
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1313,7 +1313,7 @@ pub const DeclGen = struct {
|
|||
|
||||
if (ty.optionalReprIsPayload(mod)) switch (opt.val) {
|
||||
.none => return writer.writeByte('0'),
|
||||
else => return dg.renderValue(writer, payload_ty, opt.val.toValue(), location),
|
||||
else => |payload| return dg.renderValue(writer, payload_ty, payload.toValue(), location),
|
||||
};
|
||||
|
||||
if (!location.isInitializer()) {
|
||||
|
|
@ -1325,7 +1325,7 @@ pub const DeclGen = struct {
|
|||
try writer.writeAll("{ .payload = ");
|
||||
try dg.renderValue(writer, payload_ty, switch (opt.val) {
|
||||
.none => try mod.intern(.{ .undef = payload_ty.ip_index }),
|
||||
else => opt.val,
|
||||
else => |payload| payload,
|
||||
}.toValue(), initializer_type);
|
||||
try writer.writeAll(", .is_null = ");
|
||||
try dg.renderValue(writer, Type.bool, is_null_val, initializer_type);
|
||||
|
|
|
|||
|
|
@ -3430,7 +3430,7 @@ pub const DeclGen = struct {
|
|||
const llvm_ty = try dg.lowerType(tv.ty);
|
||||
if (tv.ty.optionalReprIsPayload(mod)) return switch (opt.val) {
|
||||
.none => llvm_ty.constNull(),
|
||||
else => dg.lowerValue(.{ .ty = payload_ty, .val = opt.val.toValue() }),
|
||||
else => |payload| dg.lowerValue(.{ .ty = payload_ty, .val = payload.toValue() }),
|
||||
};
|
||||
assert(payload_ty.zigTypeTag(mod) != .Fn);
|
||||
|
||||
|
|
|
|||
|
|
@ -630,7 +630,6 @@ pub const Type = struct {
|
|||
pub fn hasWellDefinedLayout(ty: Type, mod: *Module) bool {
|
||||
return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
.int_type,
|
||||
.ptr_type,
|
||||
.vector_type,
|
||||
=> true,
|
||||
|
||||
|
|
@ -646,6 +645,7 @@ pub const Type = struct {
|
|||
|
||||
.array_type => |array_type| array_type.child.toType().hasWellDefinedLayout(mod),
|
||||
.opt_type => ty.isPtrLikeOptional(mod),
|
||||
.ptr_type => |ptr_type| ptr_type.size != .Slice,
|
||||
|
||||
.simple_type => |t| switch (t) {
|
||||
.f16,
|
||||
|
|
@ -1578,7 +1578,7 @@ pub const Type = struct {
|
|||
.int_type => |int_type| return int_type.bits,
|
||||
.ptr_type => |ptr_type| switch (ptr_type.size) {
|
||||
.Slice => return target.ptrBitWidth() * 2,
|
||||
else => return target.ptrBitWidth() * 2,
|
||||
else => return target.ptrBitWidth(),
|
||||
},
|
||||
.anyframe_type => return target.ptrBitWidth(),
|
||||
|
||||
|
|
|
|||
128
src/value.zig
128
src/value.zig
|
|
@ -363,7 +363,7 @@ pub const Value = struct {
|
|||
},
|
||||
.slice => {
|
||||
const pl = val.castTag(.slice).?.data;
|
||||
const ptr = try pl.ptr.intern(ty.optionalChild(mod), mod);
|
||||
const ptr = try pl.ptr.intern(ty.slicePtrFieldType(mod), mod);
|
||||
var ptr_key = mod.intern_pool.indexToKey(ptr).ptr;
|
||||
assert(ptr_key.len == .none);
|
||||
ptr_key.ty = ty.toIntern();
|
||||
|
|
@ -547,7 +547,6 @@ pub const Value = struct {
|
|||
return switch (val.toIntern()) {
|
||||
.bool_false => BigIntMutable.init(&space.limbs, 0).toConst(),
|
||||
.bool_true => BigIntMutable.init(&space.limbs, 1).toConst(),
|
||||
.undef => unreachable,
|
||||
.null_value => BigIntMutable.init(&space.limbs, 0).toConst(),
|
||||
else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
.runtime_value => |runtime_value| runtime_value.val.toValue().toBigIntAdvanced(space, mod, opt_sema),
|
||||
|
|
@ -564,19 +563,10 @@ pub const Value = struct {
|
|||
},
|
||||
},
|
||||
.enum_tag => |enum_tag| enum_tag.int.toValue().toBigIntAdvanced(space, mod, opt_sema),
|
||||
.ptr => |ptr| switch (ptr.len) {
|
||||
.none => switch (ptr.addr) {
|
||||
.int => |int| int.toValue().toBigIntAdvanced(space, mod, opt_sema),
|
||||
.elem => |elem| {
|
||||
const base_addr = (try elem.base.toValue().getUnsignedIntAdvanced(mod, opt_sema)).?;
|
||||
const elem_size = ptr.ty.toType().elemType2(mod).abiSize(mod);
|
||||
const new_addr = base_addr + elem.index * elem_size;
|
||||
return BigIntMutable.init(&space.limbs, new_addr).toConst();
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
.opt, .ptr => BigIntMutable.init(
|
||||
&space.limbs,
|
||||
(try val.getUnsignedIntAdvanced(mod, opt_sema)).?,
|
||||
).toConst(),
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
|
|
@ -614,10 +604,11 @@ pub const Value = struct {
|
|||
/// Asserts not undefined.
|
||||
pub fn getUnsignedIntAdvanced(val: Value, mod: *Module, opt_sema: ?*Sema) !?u64 {
|
||||
return switch (val.toIntern()) {
|
||||
.undef => unreachable,
|
||||
.bool_false => 0,
|
||||
.bool_true => 1,
|
||||
.undef => unreachable,
|
||||
else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
.undef => unreachable,
|
||||
.int => |int| switch (int.storage) {
|
||||
.big_int => |big_int| big_int.to(u64) catch null,
|
||||
.u64 => |x| x,
|
||||
|
|
@ -631,6 +622,26 @@ pub const Value = struct {
|
|||
else
|
||||
ty.toType().abiSize(mod),
|
||||
},
|
||||
.ptr => |ptr| switch (ptr.addr) {
|
||||
.int => |int| int.toValue().getUnsignedIntAdvanced(mod, opt_sema),
|
||||
.elem => |elem| {
|
||||
const base_addr = (try elem.base.toValue().getUnsignedIntAdvanced(mod, opt_sema)) orelse return null;
|
||||
const elem_size = ptr.ty.toType().elemType2(mod).abiSize(mod);
|
||||
return base_addr + elem.index * elem_size;
|
||||
},
|
||||
.field => |field| {
|
||||
const struct_ty = ptr.ty.toType().childType(mod);
|
||||
if (opt_sema) |sema| try sema.resolveTypeLayout(struct_ty);
|
||||
const base_addr = (try field.base.toValue().getUnsignedIntAdvanced(mod, opt_sema)) orelse return null;
|
||||
const field_offset = ptr.ty.toType().childType(mod).structFieldOffset(field.index, mod);
|
||||
return base_addr + field_offset;
|
||||
},
|
||||
else => null,
|
||||
},
|
||||
.opt => |opt| switch (opt.val) {
|
||||
.none => 0,
|
||||
else => |payload| payload.toValue().getUnsignedIntAdvanced(mod, opt_sema),
|
||||
},
|
||||
else => null,
|
||||
},
|
||||
};
|
||||
|
|
@ -646,7 +657,6 @@ pub const Value = struct {
|
|||
return switch (val.toIntern()) {
|
||||
.bool_false => 0,
|
||||
.bool_true => 1,
|
||||
.undef => unreachable,
|
||||
else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
.int => |int| switch (int.storage) {
|
||||
.big_int => |big_int| big_int.to(i64) catch unreachable,
|
||||
|
|
@ -830,24 +840,14 @@ pub const Value = struct {
|
|||
}
|
||||
},
|
||||
.Int, .Enum => {
|
||||
if (buffer.len == 0) return;
|
||||
const bits = ty.intInfo(mod).bits;
|
||||
const abi_size = @intCast(usize, ty.abiSize(mod));
|
||||
if (bits == 0) return;
|
||||
|
||||
const int_val = try val.enumToInt(ty, mod);
|
||||
|
||||
if (abi_size == 0) return;
|
||||
if (abi_size <= @sizeOf(u64)) {
|
||||
const ip_key = mod.intern_pool.indexToKey(int_val.toIntern());
|
||||
const int: u64 = switch (ip_key.int.storage) {
|
||||
.u64 => |x| x,
|
||||
.i64 => |x| @bitCast(u64, x),
|
||||
switch (mod.intern_pool.indexToKey((try val.enumToInt(ty, mod)).toIntern()).int.storage) {
|
||||
inline .u64, .i64 => |int| std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian),
|
||||
.big_int => |bigint| bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian),
|
||||
else => unreachable,
|
||||
};
|
||||
std.mem.writeVarPackedInt(buffer, bit_offset, bits, int, endian);
|
||||
} else {
|
||||
var bigint_buffer: BigIntSpace = undefined;
|
||||
const bigint = int_val.toBigInt(&bigint_buffer, mod);
|
||||
bigint.writePackedTwosComplement(buffer, bit_offset, bits, endian);
|
||||
}
|
||||
},
|
||||
.Float => switch (ty.floatBits(target)) {
|
||||
|
|
@ -1075,17 +1075,33 @@ pub const Value = struct {
|
|||
return Value.true;
|
||||
}
|
||||
},
|
||||
.Int, .Enum => {
|
||||
.Int, .Enum => |ty_tag| {
|
||||
if (buffer.len == 0) return mod.intValue(ty, 0);
|
||||
const int_info = ty.intInfo(mod);
|
||||
const abi_size = @intCast(usize, ty.abiSize(mod));
|
||||
|
||||
const bits = int_info.bits;
|
||||
if (bits == 0) return mod.intValue(ty, 0);
|
||||
if (bits <= 64) switch (int_info.signedness) { // Fast path for integers <= u64
|
||||
.signed => return mod.intValue(ty, std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, .signed)),
|
||||
.unsigned => return mod.intValue(ty, std.mem.readVarPackedInt(u64, buffer, bit_offset, bits, endian, .unsigned)),
|
||||
} else { // Slow path, we have to construct a big-int
|
||||
|
||||
// Fast path for integers <= u64
|
||||
if (bits <= 64) {
|
||||
const int_ty = switch (ty_tag) {
|
||||
.Int => ty,
|
||||
.Enum => ty.intTagType(mod),
|
||||
else => unreachable,
|
||||
};
|
||||
return mod.getCoerced(switch (int_info.signedness) {
|
||||
.signed => return mod.intValue(
|
||||
int_ty,
|
||||
std.mem.readVarPackedInt(i64, buffer, bit_offset, bits, endian, .signed),
|
||||
),
|
||||
.unsigned => return mod.intValue(
|
||||
int_ty,
|
||||
std.mem.readVarPackedInt(u64, buffer, bit_offset, bits, endian, .unsigned),
|
||||
),
|
||||
}, ty);
|
||||
}
|
||||
|
||||
// Slow path, we have to construct a big-int
|
||||
const abi_size = @intCast(usize, ty.abiSize(mod));
|
||||
const Limb = std.math.big.Limb;
|
||||
const limb_count = (abi_size + @sizeOf(Limb) - 1) / @sizeOf(Limb);
|
||||
const limbs_buffer = try arena.alloc(Limb, limb_count);
|
||||
|
|
@ -1093,7 +1109,6 @@ pub const Value = struct {
|
|||
var bigint = BigIntMutable.init(limbs_buffer, 0);
|
||||
bigint.readPackedTwosComplement(buffer, bit_offset, bits, endian, int_info.signedness);
|
||||
return mod.intValue_big(ty, bigint.toConst());
|
||||
}
|
||||
},
|
||||
.Float => return (try mod.intern(.{ .float = .{
|
||||
.ty = ty.toIntern(),
|
||||
|
|
@ -1764,7 +1779,7 @@ pub const Value = struct {
|
|||
},
|
||||
.opt => |opt| switch (opt.val) {
|
||||
.none => false,
|
||||
else => opt.val.toValue().canMutateComptimeVarState(mod),
|
||||
else => |payload| payload.toValue().canMutateComptimeVarState(mod),
|
||||
},
|
||||
.aggregate => |aggregate| for (aggregate.storage.values()) |elem| {
|
||||
if (elem.toValue().canMutateComptimeVarState(mod)) break true;
|
||||
|
|
@ -1949,7 +1964,15 @@ pub const Value = struct {
|
|||
start: usize,
|
||||
end: usize,
|
||||
) error{OutOfMemory}!Value {
|
||||
return switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
return switch (val.ip_index) {
|
||||
.none => switch (val.tag()) {
|
||||
.slice => val.castTag(.slice).?.data.ptr.sliceArray(mod, arena, start, end),
|
||||
.bytes => Tag.bytes.create(arena, val.castTag(.bytes).?.data[start..end]),
|
||||
.repeated => val,
|
||||
.aggregate => Tag.aggregate.create(arena, val.castTag(.aggregate).?.data[start..end]),
|
||||
else => unreachable,
|
||||
},
|
||||
else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
.ptr => |ptr| switch (ptr.addr) {
|
||||
.decl => |decl| try mod.declPtr(decl).val.sliceArray(mod, arena, start, end),
|
||||
.mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)).toValue()
|
||||
|
|
@ -1980,12 +2003,12 @@ pub const Value = struct {
|
|||
},
|
||||
} })).toValue(),
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
pub fn fieldValue(val: Value, mod: *Module, index: usize) !Value {
|
||||
return switch (val.ip_index) {
|
||||
.undef => Value.undef,
|
||||
.none => switch (val.tag()) {
|
||||
.aggregate => {
|
||||
const field_values = val.castTag(.aggregate).?.data;
|
||||
|
|
@ -1999,6 +2022,9 @@ pub const Value = struct {
|
|||
else => unreachable,
|
||||
},
|
||||
else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
.undef => |ty| (try mod.intern(.{
|
||||
.undef = ty.toType().structFieldType(index, mod).toIntern(),
|
||||
})).toValue(),
|
||||
.aggregate => |aggregate| switch (aggregate.storage) {
|
||||
.bytes => |bytes| try mod.intern(.{ .int = .{
|
||||
.ty = .u8_type,
|
||||
|
|
@ -2108,6 +2134,7 @@ pub const Value = struct {
|
|||
.null_value => true,
|
||||
|
||||
else => return switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
.undef => unreachable,
|
||||
.int => {
|
||||
var buf: BigIntSpace = undefined;
|
||||
return val.toBigInt(&buf, mod).eqZero();
|
||||
|
|
@ -2141,9 +2168,13 @@ pub const Value = struct {
|
|||
|
||||
/// Value of the optional, null if optional has no payload.
|
||||
pub fn optionalValue(val: Value, mod: *const Module) ?Value {
|
||||
return switch (mod.intern_pool.indexToKey(val.toIntern()).opt.val) {
|
||||
return switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
.opt => |opt| switch (opt.val) {
|
||||
.none => null,
|
||||
else => |index| index.toValue(),
|
||||
else => |payload| payload.toValue(),
|
||||
},
|
||||
.ptr => val,
|
||||
else => unreachable,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -2152,6 +2183,7 @@ pub const Value = struct {
|
|||
return switch (self.toIntern()) {
|
||||
.undef => unreachable,
|
||||
else => switch (mod.intern_pool.indexToKey(self.toIntern())) {
|
||||
.undef => unreachable,
|
||||
.float => true,
|
||||
else => false,
|
||||
},
|
||||
|
|
@ -2182,9 +2214,8 @@ pub const Value = struct {
|
|||
}
|
||||
|
||||
pub fn intToFloatScalar(val: Value, float_ty: Type, mod: *Module, opt_sema: ?*Sema) !Value {
|
||||
return switch (val.toIntern()) {
|
||||
.undef => val,
|
||||
else => return switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
return switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
.undef => (try mod.intern(.{ .undef = float_ty.toIntern() })).toValue(),
|
||||
.int => |int| switch (int.storage) {
|
||||
.big_int => |big_int| {
|
||||
const float = bigIntToFloat(big_int.limbs, big_int.positive);
|
||||
|
|
@ -2203,7 +2234,6 @@ pub const Value = struct {
|
|||
},
|
||||
},
|
||||
else => unreachable,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -455,21 +455,21 @@ class InternPool_Index_SynthProvider:
|
|||
elif encoding_field.name == 'trailing':
|
||||
trailing_data = lldb.SBData()
|
||||
for trailing_field in encoding_field.type.fields:
|
||||
if trailing_field.type.IsAggregateType():
|
||||
trailing_data.Append(extra.GetChildAtIndex(extra_index).address_of.data)
|
||||
len = dynamic_values['trailing.%s.len' % trailing_field.name].unsigned
|
||||
trailing_data.Append(lldb.SBData.CreateDataFromInt(len, trailing_data.GetAddressByteSize()))
|
||||
extra_index += len
|
||||
else:
|
||||
pass
|
||||
trailing_len = dynamic_values['trailing.%s.len' % trailing_field.name].unsigned
|
||||
trailing_data.Append(lldb.SBData.CreateDataFromInt(trailing_len, trailing_data.GetAddressByteSize()))
|
||||
extra_index += trailing_len
|
||||
self.trailing = self.data.CreateValueFromData('trailing', trailing_data, encoding_field.type)
|
||||
else:
|
||||
path = encoding_field.type.GetPointeeType().name.removeprefix('%s::' % encoding_type.name).removeprefix('%s.' % encoding_type.name).partition('__')[0].split('.')
|
||||
if path[0] == 'data':
|
||||
dynamic_value = self.data
|
||||
for name in path[1:]:
|
||||
dynamic_value = dynamic_value.GetChildMemberWithName(name)
|
||||
for path in encoding_field.type.GetPointeeType().name.removeprefix('%s::' % encoding_type.name).removeprefix('%s.' % encoding_type.name).partition('__')[0].split(' orelse '):
|
||||
if path.startswith('data.'):
|
||||
root = self.data
|
||||
path = path[len('data'):]
|
||||
else: return
|
||||
dynamic_value = root.GetValueForExpressionPath(path)
|
||||
if dynamic_value:
|
||||
dynamic_values[encoding_field.name] = dynamic_value
|
||||
break
|
||||
except: pass
|
||||
def has_children(self): return True
|
||||
def num_children(self): return 2 + (self.trailing is not None)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue