mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
behavior: additional llvm fixes
This commit is contained in:
parent
3b6ca1d35b
commit
3064d2aa7b
@ -3131,7 +3131,8 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
},
|
||||
|
||||
.enum_type => |enum_type| {
|
||||
assert(enum_type.tag_ty != .none);
|
||||
assert(enum_type.tag_ty == .noreturn_type or ip.isIntegerType(enum_type.tag_ty));
|
||||
for (enum_type.values) |value| assert(ip.typeOf(value) == enum_type.tag_ty);
|
||||
assert(enum_type.names_map == .none);
|
||||
assert(enum_type.values_map == .none);
|
||||
|
||||
@ -3622,14 +3623,12 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
|
||||
if (bytes.len != len) {
|
||||
assert(bytes.len == len_including_sentinel);
|
||||
assert(bytes[len] == ip.indexToKey(sentinel).int.storage.u64);
|
||||
unreachable;
|
||||
}
|
||||
},
|
||||
.elems => |elems| {
|
||||
if (elems.len != len) {
|
||||
assert(elems.len == len_including_sentinel);
|
||||
assert(elems[len] == sentinel);
|
||||
unreachable;
|
||||
}
|
||||
},
|
||||
.repeated_elem => |elem| {
|
||||
@ -3832,7 +3831,7 @@ pub const IncompleteEnumType = struct {
|
||||
values_start: u32,
|
||||
|
||||
pub fn setTagType(self: @This(), ip: *InternPool, tag_ty: Index) void {
|
||||
assert(tag_ty != .none);
|
||||
assert(tag_ty == .noreturn_type or ip.isIntegerType(tag_ty));
|
||||
ip.extra.items[self.tag_ty_index] = @enumToInt(tag_ty);
|
||||
}
|
||||
|
||||
@ -3863,6 +3862,7 @@ pub const IncompleteEnumType = struct {
|
||||
gpa: Allocator,
|
||||
value: Index,
|
||||
) Allocator.Error!?u32 {
|
||||
assert(ip.typeOf(value) == @intToEnum(Index, ip.extra.items[self.tag_ty_index]));
|
||||
const map = &ip.maps.items[@enumToInt(self.values_map.unwrap().?)];
|
||||
const field_index = map.count();
|
||||
const indexes = ip.extra.items[self.values_start..][0..field_index];
|
||||
@ -4346,7 +4346,7 @@ pub fn sliceLen(ip: InternPool, i: Index) Index {
|
||||
/// * ptr <=> ptr
|
||||
/// * opt ptr <=> ptr
|
||||
/// * opt ptr <=> opt ptr
|
||||
/// * int => ptr
|
||||
/// * int <=> ptr
|
||||
/// * null_value => opt
|
||||
/// * payload => opt
|
||||
/// * error set <=> error set
|
||||
@ -4386,18 +4386,18 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
|
||||
.ty = new_ty,
|
||||
.index = func.index,
|
||||
} }),
|
||||
.int => |int| if (ip.isIntegerType(new_ty))
|
||||
return getCoercedInts(ip, gpa, int, new_ty)
|
||||
else if (ip.isEnumType(new_ty))
|
||||
return ip.get(gpa, .{ .enum_tag = .{
|
||||
.int => |int| switch (ip.indexToKey(new_ty)) {
|
||||
.enum_type => |enum_type| return ip.get(gpa, .{ .enum_tag = .{
|
||||
.ty = new_ty,
|
||||
.int = val,
|
||||
} })
|
||||
else if (ip.isPointerType(new_ty))
|
||||
return ip.get(gpa, .{ .ptr = .{
|
||||
.ty = new_ty,
|
||||
.addr = .{ .int = val },
|
||||
.int = try ip.getCoerced(gpa, val, enum_type.tag_ty),
|
||||
} }),
|
||||
.ptr_type => return ip.get(gpa, .{ .ptr = .{
|
||||
.ty = new_ty,
|
||||
.addr = .{ .int = try ip.getCoerced(gpa, val, .usize_type) },
|
||||
} }),
|
||||
else => if (ip.isIntegerType(new_ty))
|
||||
return getCoercedInts(ip, gpa, int, new_ty),
|
||||
},
|
||||
.enum_tag => |enum_tag| if (ip.isIntegerType(new_ty))
|
||||
return getCoercedInts(ip, gpa, ip.indexToKey(enum_tag.int).int, new_ty),
|
||||
.enum_literal => |enum_literal| switch (ip.indexToKey(new_ty)) {
|
||||
@ -4421,7 +4421,12 @@ pub fn getCoerced(ip: *InternPool, gpa: Allocator, val: Index, new_ty: Index) Al
|
||||
.ty = new_ty,
|
||||
.addr = ptr.addr,
|
||||
.len = ptr.len,
|
||||
} }),
|
||||
} })
|
||||
else if (ip.isIntegerType(new_ty))
|
||||
switch (ptr.addr) {
|
||||
.int => |int| return ip.getCoerced(gpa, int, new_ty),
|
||||
else => {},
|
||||
},
|
||||
.opt => |opt| if (ip.isPointerType(new_ty))
|
||||
return switch (opt.val) {
|
||||
.none => try ip.get(gpa, .{ .ptr = .{
|
||||
|
||||
@ -707,6 +707,10 @@ pub const Decl = struct {
|
||||
return TypedValue{ .ty = decl.ty, .val = decl.val };
|
||||
}
|
||||
|
||||
pub fn internValue(decl: Decl, mod: *Module) Allocator.Error!InternPool.Index {
|
||||
return decl.val.intern(decl.ty, mod);
|
||||
}
|
||||
|
||||
pub fn isFunction(decl: Decl, mod: *const Module) !bool {
|
||||
const tv = try decl.typedValue();
|
||||
return tv.ty.zigTypeTag(mod) == .Fn;
|
||||
@ -7073,7 +7077,7 @@ pub fn atomicPtrAlignment(
|
||||
|
||||
const int_ty = switch (ty.zigTypeTag(mod)) {
|
||||
.Int => ty,
|
||||
.Enum => try ty.intTagType(mod),
|
||||
.Enum => ty.intTagType(mod),
|
||||
.Float => {
|
||||
const bit_count = ty.floatBits(target);
|
||||
if (bit_count > max_atomic_bits) {
|
||||
|
||||
133
src/Sema.zig
133
src/Sema.zig
@ -3291,7 +3291,8 @@ fn zirErrorSetDecl(
|
||||
while (extra_index < extra_index_end) : (extra_index += 2) { // +2 to skip over doc_string
|
||||
const str_index = sema.code.extra[extra_index];
|
||||
const name = sema.code.nullTerminatedString(str_index);
|
||||
const name_ip = try mod.intern_pool.getOrPutString(gpa, name);
|
||||
const kv = try mod.getErrorValue(name);
|
||||
const name_ip = try mod.intern_pool.getOrPutString(gpa, kv.key);
|
||||
const result = names.getOrPutAssumeCapacity(name_ip);
|
||||
assert(!result.found_existing); // verified in AstGen
|
||||
}
|
||||
@ -6409,7 +6410,7 @@ fn zirCall(
|
||||
|
||||
// Generate args to comptime params in comptime block.
|
||||
defer block.is_comptime = parent_comptime;
|
||||
if (arg_index < fn_params_len and func_ty_info.paramIsComptime(@intCast(u5, arg_index))) {
|
||||
if (arg_index < @min(fn_params_len, 32) and func_ty_info.paramIsComptime(@intCast(u5, arg_index))) {
|
||||
block.is_comptime = true;
|
||||
// TODO set comptime_reason
|
||||
}
|
||||
@ -7077,14 +7078,13 @@ fn analyzeCall(
|
||||
assert(!func_ty_info.is_generic);
|
||||
|
||||
const args = try sema.arena.alloc(Air.Inst.Ref, uncasted_args.len);
|
||||
const fn_info = mod.typeToFunc(func_ty).?;
|
||||
for (uncasted_args, 0..) |uncasted_arg, i| {
|
||||
if (i < fn_params_len) {
|
||||
const opts: CoerceOpts = .{ .param_src = .{
|
||||
.func_inst = func,
|
||||
.param_i = @intCast(u32, i),
|
||||
} };
|
||||
const param_ty = fn_info.param_types[i].toType();
|
||||
const param_ty = mod.typeToFunc(func_ty).?.param_types[i].toType();
|
||||
args[i] = sema.analyzeCallArg(
|
||||
block,
|
||||
.unneeded,
|
||||
@ -8267,7 +8267,7 @@ fn zirEnumToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
};
|
||||
const enum_tag_ty = sema.typeOf(enum_tag);
|
||||
|
||||
const int_tag_ty = try enum_tag_ty.intTagType(mod);
|
||||
const int_tag_ty = enum_tag_ty.intTagType(mod);
|
||||
|
||||
if (try sema.typeHasOnePossibleValue(enum_tag_ty)) |opv| {
|
||||
return sema.addConstant(int_tag_ty, try mod.getCoerced(opv, int_tag_ty));
|
||||
@ -8299,12 +8299,9 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
|
||||
if (try sema.resolveMaybeUndefVal(operand)) |int_val| {
|
||||
if (dest_ty.isNonexhaustiveEnum(mod)) {
|
||||
const int_tag_ty = try dest_ty.intTagType(mod);
|
||||
const int_tag_ty = dest_ty.intTagType(mod);
|
||||
if (try sema.intFitsInType(int_val, int_tag_ty, null)) {
|
||||
return sema.addConstant(dest_ty, (try mod.intern(.{ .enum_tag = .{
|
||||
.ty = dest_ty.toIntern(),
|
||||
.int = int_val.toIntern(),
|
||||
} })).toValue());
|
||||
return sema.addConstant(dest_ty, try mod.getCoerced(int_val, dest_ty));
|
||||
}
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(
|
||||
@ -8336,7 +8333,7 @@ fn zirIntToEnum(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
};
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
}
|
||||
return sema.addConstant(dest_ty, int_val);
|
||||
return sema.addConstant(dest_ty, try mod.getCoerced(int_val, dest_ty));
|
||||
}
|
||||
|
||||
if (try sema.typeHasOnePossibleValue(dest_ty)) |opv| {
|
||||
@ -9513,7 +9510,7 @@ 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, ptr_val);
|
||||
return sema.addConstant(Type.usize, try mod.getCoerced(ptr_val, Type.usize));
|
||||
}
|
||||
try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src);
|
||||
return block.addUnOp(.ptrtoint, ptr);
|
||||
@ -9651,7 +9648,7 @@ fn intCast(
|
||||
// range shrinkage
|
||||
// requirement: int value fits into target type
|
||||
if (wanted_value_bits < actual_value_bits) {
|
||||
const dest_max_val_scalar = try dest_scalar_ty.maxIntScalar(mod, operand_ty);
|
||||
const dest_max_val_scalar = try dest_scalar_ty.maxIntScalar(mod, operand_scalar_ty);
|
||||
const dest_max_val = try sema.splat(operand_ty, dest_max_val_scalar);
|
||||
const dest_max = try sema.addConstant(operand_ty, dest_max_val);
|
||||
const diff = try block.addBinOp(.subwrap, dest_max, operand);
|
||||
@ -12848,7 +12845,7 @@ fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||
if (res_sent_val) |sent_val| {
|
||||
const elem_index = try sema.addIntUnsigned(Type.usize, result_len);
|
||||
const elem_ptr = try block.addPtrElemPtr(alloc, elem_index, elem_ptr_ty);
|
||||
const init = try sema.addConstant(lhs_info.elem_type, sent_val);
|
||||
const init = try sema.addConstant(lhs_info.elem_type, try mod.getCoerced(sent_val, lhs_info.elem_type));
|
||||
try sema.storePtr2(block, src, elem_ptr, src, init, lhs_src, .store);
|
||||
}
|
||||
|
||||
@ -19236,7 +19233,8 @@ fn zirReify(
|
||||
const name_val = try elem_val.fieldValue(mod, elem_fields.getIndex("name").?);
|
||||
|
||||
const name_str = try name_val.toAllocatedBytes(Type.slice_const_u8, sema.arena, mod);
|
||||
const name_ip = try mod.intern_pool.getOrPutString(gpa, name_str);
|
||||
const kv = try mod.getErrorValue(name_str);
|
||||
const name_ip = try mod.intern_pool.getOrPutString(gpa, kv.key);
|
||||
const gop = names.getOrPutAssumeCapacity(name_ip);
|
||||
if (gop.found_existing) {
|
||||
return sema.fail(block, src, "duplicate error '{s}'", .{name_str});
|
||||
@ -19346,7 +19344,7 @@ fn zirReify(
|
||||
return sema.failWithOwnedErrorMsg(msg);
|
||||
}
|
||||
|
||||
if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, value_val.toIntern())) |other| {
|
||||
if (try incomplete_enum.addFieldValue(&mod.intern_pool, gpa, (try mod.getCoerced(value_val, int_tag_ty)).toIntern())) |other| {
|
||||
const msg = msg: {
|
||||
const msg = try sema.errMsg(block, src, "enum tag value {} already taken", .{value_val.fmtValue(Type.comptime_int, mod)});
|
||||
errdefer msg.destroy(gpa);
|
||||
@ -20263,7 +20261,7 @@ fn zirErrSetCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
|
||||
}
|
||||
}
|
||||
|
||||
return sema.addConstant(dest_ty, val);
|
||||
return sema.addConstant(dest_ty, try mod.getCoerced(val, dest_ty));
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src, operand_src);
|
||||
@ -20421,7 +20419,7 @@ fn zirConstCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
|
||||
const dest_ty = try Type.ptr(sema.arena, mod, ptr_info);
|
||||
|
||||
if (try sema.resolveMaybeUndefVal(operand)) |operand_val| {
|
||||
return sema.addConstant(dest_ty, operand_val);
|
||||
return sema.addConstant(dest_ty, try mod.getCoerced(operand_val, dest_ty));
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src, null);
|
||||
@ -20624,7 +20622,7 @@ fn zirBitCount(
|
||||
for (elems, 0..) |*elem, i| {
|
||||
const elem_val = try val.elemValue(mod, i);
|
||||
const count = comptimeOp(elem_val, scalar_ty, mod);
|
||||
elem.* = (try mod.intValue(scalar_ty, count)).toIntern();
|
||||
elem.* = (try mod.intValue(result_scalar_ty, count)).toIntern();
|
||||
}
|
||||
return sema.addConstant(result_ty, (try mod.intern(.{ .aggregate = .{
|
||||
.ty = result_ty.toIntern(),
|
||||
@ -22385,7 +22383,9 @@ fn analyzeMinMax(
|
||||
if (std.debug.runtime_safety) {
|
||||
assert(try sema.intFitsInType(val, refined_ty, null));
|
||||
}
|
||||
cur_minmax = try sema.addConstant(refined_ty, try mod.getCoerced(val, refined_ty));
|
||||
cur_minmax = try sema.addConstant(refined_ty, (try sema.resolveMaybeUndefVal(
|
||||
try sema.coerceInMemory(block, val, orig_ty, refined_ty, src),
|
||||
)).?);
|
||||
}
|
||||
|
||||
break :refined refined_ty;
|
||||
@ -23684,7 +23684,7 @@ fn validateExternType(
|
||||
return !target_util.fnCallConvAllowsZigTypes(target, ty.fnCallingConvention(mod));
|
||||
},
|
||||
.Enum => {
|
||||
return sema.validateExternType(try ty.intTagType(mod), position);
|
||||
return sema.validateExternType(ty.intTagType(mod), position);
|
||||
},
|
||||
.Struct, .Union => switch (ty.containerLayout(mod)) {
|
||||
.Extern => return true,
|
||||
@ -23762,7 +23762,7 @@ fn explainWhyTypeIsNotExtern(
|
||||
}
|
||||
},
|
||||
.Enum => {
|
||||
const tag_ty = try ty.intTagType(mod);
|
||||
const tag_ty = ty.intTagType(mod);
|
||||
try mod.errNoteNonLazy(src_loc, msg, "enum tag type '{}' is not extern compatible", .{tag_ty.fmt(sema.mod)});
|
||||
try sema.explainWhyTypeIsNotExtern(msg, src_loc, tag_ty, position);
|
||||
},
|
||||
@ -25412,7 +25412,8 @@ fn elemVal(
|
||||
const elem_ptr_ty = try sema.elemPtrType(indexable_ty, index);
|
||||
const elem_ptr_val = try indexable_val.elemPtr(elem_ptr_ty, index, mod);
|
||||
if (try sema.pointerDeref(block, indexable_src, elem_ptr_val, elem_ptr_ty)) |elem_val| {
|
||||
return sema.addConstant(indexable_ty.elemType2(mod), elem_val);
|
||||
const result_ty = indexable_ty.elemType2(mod);
|
||||
return sema.addConstant(result_ty, try mod.getCoerced(elem_val, result_ty));
|
||||
}
|
||||
break :rs indexable_src;
|
||||
};
|
||||
@ -26603,6 +26604,10 @@ fn coerceInMemory(
|
||||
.storage = .{ .elems = dest_elems },
|
||||
} })).toValue());
|
||||
},
|
||||
.float => |float| return sema.addConstant(dst_ty, (try mod.intern(.{ .float = .{
|
||||
.ty = dst_ty.toIntern(),
|
||||
.storage = float.storage,
|
||||
} })).toValue()),
|
||||
else => return sema.addConstant(dst_ty, try mod.getCoerced(val, dst_ty)),
|
||||
}
|
||||
}
|
||||
@ -26983,8 +26988,11 @@ fn coerceInMemoryAllowed(
|
||||
if (dest_ty.eql(src_ty, mod))
|
||||
return .ok;
|
||||
|
||||
const dest_tag = dest_ty.zigTypeTag(mod);
|
||||
const src_tag = src_ty.zigTypeTag(mod);
|
||||
|
||||
// Differently-named integers with the same number of bits.
|
||||
if (dest_ty.zigTypeTag(mod) == .Int and src_ty.zigTypeTag(mod) == .Int) {
|
||||
if (dest_tag == .Int and src_tag == .Int) {
|
||||
const dest_info = dest_ty.intInfo(mod);
|
||||
const src_info = src_ty.intInfo(mod);
|
||||
|
||||
@ -27009,7 +27017,7 @@ fn coerceInMemoryAllowed(
|
||||
}
|
||||
|
||||
// Differently-named floats with the same number of bits.
|
||||
if (dest_ty.zigTypeTag(mod) == .Float and src_ty.zigTypeTag(mod) == .Float) {
|
||||
if (dest_tag == .Float and src_tag == .Float) {
|
||||
const dest_bits = dest_ty.floatBits(target);
|
||||
const src_bits = src_ty.floatBits(target);
|
||||
if (dest_bits == src_bits) {
|
||||
@ -27031,9 +27039,6 @@ fn coerceInMemoryAllowed(
|
||||
return try sema.coerceInMemoryAllowedPtrs(block, dest_ty, src_ty, dest_ty, src_ty, dest_is_mut, target, dest_src, src_src);
|
||||
}
|
||||
|
||||
const dest_tag = dest_ty.zigTypeTag(mod);
|
||||
const src_tag = src_ty.zigTypeTag(mod);
|
||||
|
||||
// Functions
|
||||
if (dest_tag == .Fn and src_tag == .Fn) {
|
||||
return try sema.coerceInMemoryAllowedFns(block, dest_ty, src_ty, target, dest_src, src_src);
|
||||
@ -27808,7 +27813,7 @@ fn beginComptimePtrMutation(
|
||||
.comptime_field => |comptime_field| {
|
||||
const duped = try sema.arena.create(Value);
|
||||
duped.* = comptime_field.toValue();
|
||||
return sema.beginComptimePtrMutationInner(block, src, mod.intern_pool.typeOf(ptr_val.toIntern()).toType(), duped, ptr_elem_ty, .{
|
||||
return sema.beginComptimePtrMutationInner(block, src, mod.intern_pool.typeOf(comptime_field).toType(), duped, ptr_elem_ty, .{
|
||||
.decl = undefined,
|
||||
.runtime_index = .comptime_field_ptr,
|
||||
});
|
||||
@ -27864,7 +27869,21 @@ fn beginComptimePtrMutation(
|
||||
.direct => |val_ptr| {
|
||||
const payload_ty = parent.ty.optionalChild(mod);
|
||||
switch (val_ptr.ip_index) {
|
||||
.undef, .null_value => {
|
||||
.none => return ComptimePtrMutationKit{
|
||||
.mut_decl = parent.mut_decl,
|
||||
.pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data },
|
||||
.ty = payload_ty,
|
||||
},
|
||||
else => {
|
||||
const payload_val = switch (mod.intern_pool.indexToKey(val_ptr.ip_index)) {
|
||||
.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 => unreachable,
|
||||
};
|
||||
|
||||
// An optional has been initialized to undefined at comptime and now we
|
||||
// are for the first time setting the payload. We must change the
|
||||
// representation of the optional from `undef` to `opt_payload`.
|
||||
@ -27874,7 +27893,7 @@ fn beginComptimePtrMutation(
|
||||
const payload = try arena.create(Value.Payload.SubValue);
|
||||
payload.* = .{
|
||||
.base = .{ .tag = .opt_payload },
|
||||
.data = (try mod.intern(.{ .undef = payload_ty.toIntern() })).toValue(),
|
||||
.data = payload_val.toValue(),
|
||||
};
|
||||
|
||||
val_ptr.* = Value.initPayload(&payload.base);
|
||||
@ -27885,24 +27904,6 @@ fn beginComptimePtrMutation(
|
||||
.ty = payload_ty,
|
||||
};
|
||||
},
|
||||
.none => switch (val_ptr.tag()) {
|
||||
.opt_payload => return ComptimePtrMutationKit{
|
||||
.mut_decl = parent.mut_decl,
|
||||
.pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data },
|
||||
.ty = payload_ty,
|
||||
},
|
||||
|
||||
else => return ComptimePtrMutationKit{
|
||||
.mut_decl = parent.mut_decl,
|
||||
.pointee = .{ .direct = val_ptr },
|
||||
.ty = payload_ty,
|
||||
},
|
||||
},
|
||||
else => return ComptimePtrMutationKit{
|
||||
.mut_decl = parent.mut_decl,
|
||||
.pointee = .{ .direct = val_ptr },
|
||||
.ty = payload_ty,
|
||||
},
|
||||
}
|
||||
},
|
||||
.bad_decl_ty, .bad_ptr_ty => return parent,
|
||||
@ -33339,16 +33340,20 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
|
||||
return null;
|
||||
},
|
||||
.auto, .explicit => switch (enum_type.names.len) {
|
||||
0 => return Value.@"unreachable",
|
||||
1 => return try mod.getCoerced((if (enum_type.values.len == 0)
|
||||
try mod.intern(.{ .int = .{
|
||||
.ty = enum_type.tag_ty,
|
||||
.storage = .{ .u64 = 0 },
|
||||
} })
|
||||
else
|
||||
enum_type.values[0]).toValue(), ty),
|
||||
else => return null,
|
||||
.auto, .explicit => {
|
||||
if (enum_type.tag_ty.toType().hasRuntimeBits(mod)) return null;
|
||||
|
||||
switch (enum_type.names.len) {
|
||||
0 => return Value.@"unreachable",
|
||||
1 => return try mod.getCoerced((if (enum_type.values.len == 0)
|
||||
try mod.intern(.{ .int = .{
|
||||
.ty = enum_type.tag_ty,
|
||||
.storage = .{ .u64 = 0 },
|
||||
} })
|
||||
else
|
||||
enum_type.values[0]).toValue(), ty),
|
||||
else => return null,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@ -34241,13 +34246,9 @@ fn intFitsInType(
|
||||
if (ty.toIntern() == .comptime_int_type) return true;
|
||||
const info = ty.intInfo(mod);
|
||||
switch (val.toIntern()) {
|
||||
.undef,
|
||||
.zero,
|
||||
.zero_usize,
|
||||
.zero_u8,
|
||||
=> return true,
|
||||
|
||||
.zero_usize, .zero_u8 => return true,
|
||||
else => switch (mod.intern_pool.indexToKey(val.toIntern())) {
|
||||
.undef => return true,
|
||||
.variable, .extern_func, .func, .ptr => {
|
||||
const target = mod.getTarget();
|
||||
const ptr_bits = target.ptrBitWidth();
|
||||
@ -34553,7 +34554,7 @@ fn isNoReturn(sema: *Sema, ref: Air.Inst.Ref) bool {
|
||||
return sema.typeOf(ref).isNoReturn(sema.mod);
|
||||
}
|
||||
|
||||
/// Avoids crashing the compiler when asking if inferred allocations are known to be a certain type.
|
||||
/// Avoids crashing the compiler when asking if inferred allocations are known to be a certain zig type.
|
||||
fn isKnownZigType(sema: *Sema, ref: Air.Inst.Ref, tag: std.builtin.TypeId) bool {
|
||||
if (Air.refToIndex(ref)) |inst| switch (sema.air_instructions.items(.tag)[inst]) {
|
||||
.inferred_alloc, .inferred_alloc_comptime => return false,
|
||||
|
||||
@ -302,10 +302,14 @@ fn printAggregate(
|
||||
var i: u32 = 0;
|
||||
while (i < max_len) : (i += 1) {
|
||||
if (i != 0) try writer.writeAll(", ");
|
||||
switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
.struct_type, .anon_struct_type => try writer.print(".{s} = ", .{ty.structFieldName(i, mod)}),
|
||||
else => {},
|
||||
}
|
||||
if (switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
.struct_type => |struct_type| mod.structPtrUnwrap(struct_type.index).?.fields.keys()[i],
|
||||
.anon_struct_type => |anon_struct_type| if (anon_struct_type.isTuple())
|
||||
null
|
||||
else
|
||||
mod.intern_pool.stringToSlice(anon_struct_type.names[i]),
|
||||
else => unreachable,
|
||||
}) |field_name| try writer.print(".{s} = ", .{field_name});
|
||||
try print(.{
|
||||
.ty = ty.structFieldType(i, mod),
|
||||
.val = try val.fieldValue(mod, i),
|
||||
|
||||
@ -4527,7 +4527,7 @@ fn cmp(
|
||||
}
|
||||
},
|
||||
.Float => return self.fail("TODO ARM cmp floats", .{}),
|
||||
.Enum => try lhs_ty.intTagType(mod),
|
||||
.Enum => lhs_ty.intTagType(mod),
|
||||
.Int => lhs_ty,
|
||||
.Bool => Type.u1,
|
||||
.Pointer => Type.usize,
|
||||
|
||||
@ -4475,7 +4475,7 @@ fn cmp(
|
||||
}
|
||||
},
|
||||
.Float => return self.fail("TODO ARM cmp floats", .{}),
|
||||
.Enum => try lhs_ty.intTagType(mod),
|
||||
.Enum => lhs_ty.intTagType(mod),
|
||||
.Int => lhs_ty,
|
||||
.Bool => Type.u1,
|
||||
.Pointer => Type.usize,
|
||||
|
||||
@ -1435,7 +1435,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
|
||||
|
||||
const int_ty = switch (lhs_ty.zigTypeTag(mod)) {
|
||||
.Vector => unreachable, // Handled by cmp_vector.
|
||||
.Enum => try lhs_ty.intTagType(mod),
|
||||
.Enum => lhs_ty.intTagType(mod),
|
||||
.Int => lhs_ty,
|
||||
.Bool => Type.u1,
|
||||
.Pointer => Type.usize,
|
||||
|
||||
@ -6883,7 +6883,7 @@ fn getTagNameFunction(func: *CodeGen, enum_ty: Type) InnerError!u32 {
|
||||
return loc.index;
|
||||
}
|
||||
|
||||
const int_tag_ty = try enum_ty.intTagType(mod);
|
||||
const int_tag_ty = enum_ty.intTagType(mod);
|
||||
|
||||
if (int_tag_ty.bitSize(mod) > 64) {
|
||||
return func.fail("TODO: Implement @tagName for enums with tag size larger than 64 bits", .{});
|
||||
|
||||
@ -312,7 +312,7 @@ pub fn generateSymbol(
|
||||
}
|
||||
},
|
||||
.enum_tag => |enum_tag| {
|
||||
const int_tag_ty = try typed_value.ty.intTagType(mod);
|
||||
const int_tag_ty = typed_value.ty.intTagType(mod);
|
||||
switch (try generateSymbol(bin_file, src_loc, .{
|
||||
.ty = int_tag_ty,
|
||||
.val = try mod.getCoerced(enum_tag.int.toValue(), int_tag_ty),
|
||||
|
||||
@ -2773,7 +2773,7 @@ pub const DeclGen = struct {
|
||||
return dg.context.intType(info.bits);
|
||||
},
|
||||
.Enum => {
|
||||
const int_ty = try t.intTagType(mod);
|
||||
const int_ty = t.intTagType(mod);
|
||||
const bit_count = int_ty.intInfo(mod).bits;
|
||||
assert(bit_count != 0);
|
||||
return dg.context.intType(bit_count);
|
||||
@ -4148,9 +4148,7 @@ pub const DeclGen = struct {
|
||||
const mod = dg.module;
|
||||
const int_ty = switch (ty.zigTypeTag(mod)) {
|
||||
.Int => ty,
|
||||
.Enum => ty.intTagType(mod) catch |err| switch (err) {
|
||||
error.OutOfMemory => @panic("OOM"),
|
||||
},
|
||||
.Enum => ty.intTagType(mod),
|
||||
.Float => {
|
||||
if (!is_rmw_xchg) return null;
|
||||
return dg.context.intType(@intCast(c_uint, ty.abiSize(mod) * 8));
|
||||
@ -5100,7 +5098,7 @@ pub const FuncGen = struct {
|
||||
const mod = self.dg.module;
|
||||
const scalar_ty = operand_ty.scalarType(mod);
|
||||
const int_ty = switch (scalar_ty.zigTypeTag(mod)) {
|
||||
.Enum => try scalar_ty.intTagType(mod),
|
||||
.Enum => scalar_ty.intTagType(mod),
|
||||
.Int, .Bool, .Pointer, .ErrorSet => scalar_ty,
|
||||
.Optional => blk: {
|
||||
const payload_ty = operand_ty.optionalChild(mod);
|
||||
|
||||
@ -700,7 +700,7 @@ pub const DeclGen = struct {
|
||||
.enum_tag => {
|
||||
const int_val = try val.enumToInt(ty, mod);
|
||||
|
||||
const int_ty = try ty.intTagType(mod);
|
||||
const int_ty = ty.intTagType(mod);
|
||||
|
||||
try self.lower(int_ty, int_val);
|
||||
},
|
||||
@ -1156,7 +1156,7 @@ pub const DeclGen = struct {
|
||||
return try self.intType(int_info.signedness, int_info.bits);
|
||||
},
|
||||
.Enum => {
|
||||
const tag_ty = try ty.intTagType(mod);
|
||||
const tag_ty = ty.intTagType(mod);
|
||||
return self.resolveType(tag_ty, repr);
|
||||
},
|
||||
.Float => {
|
||||
@ -3053,7 +3053,7 @@ pub const DeclGen = struct {
|
||||
break :blk if (backing_bits <= 32) @as(u32, 1) else 2;
|
||||
},
|
||||
.Enum => blk: {
|
||||
const int_ty = try cond_ty.intTagType(mod);
|
||||
const int_ty = cond_ty.intTagType(mod);
|
||||
const int_info = int_ty.intInfo(mod);
|
||||
const backing_bits = self.backingIntBits(int_info.bits) orelse {
|
||||
return self.todo("implement composite int switch", .{});
|
||||
|
||||
54
src/type.zig
54
src/type.zig
@ -1842,17 +1842,15 @@ pub const Type = struct {
|
||||
/// See also `isPtrLikeOptional`.
|
||||
pub fn optionalReprIsPayload(ty: Type, mod: *const Module) bool {
|
||||
return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
.opt_type => |child| switch (child.toType().zigTypeTag(mod)) {
|
||||
.Pointer => {
|
||||
const info = child.toType().ptrInfo(mod);
|
||||
return switch (info.size) {
|
||||
.C => false,
|
||||
else => !info.@"allowzero",
|
||||
};
|
||||
.opt_type => |child_type| switch (mod.intern_pool.indexToKey(child_type)) {
|
||||
.ptr_type => |ptr_type| switch (ptr_type.size) {
|
||||
.C => false,
|
||||
.Slice, .Many, .One => !ptr_type.is_allowzero,
|
||||
},
|
||||
.ErrorSet => true,
|
||||
.error_set_type => true,
|
||||
else => false,
|
||||
},
|
||||
.ptr_type => |ptr_type| ptr_type.size == .C,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
@ -2570,23 +2568,27 @@ pub const Type = struct {
|
||||
|
||||
return null;
|
||||
},
|
||||
.auto, .explicit => switch (enum_type.names.len) {
|
||||
0 => return Value.@"unreachable",
|
||||
1 => {
|
||||
if (enum_type.values.len == 0) {
|
||||
const only = try mod.intern(.{ .enum_tag = .{
|
||||
.ty = ty.toIntern(),
|
||||
.int = try mod.intern(.{ .int = .{
|
||||
.ty = enum_type.tag_ty,
|
||||
.storage = .{ .u64 = 0 },
|
||||
} }),
|
||||
} });
|
||||
return only.toValue();
|
||||
} else {
|
||||
return enum_type.values[0].toValue();
|
||||
}
|
||||
},
|
||||
else => return null,
|
||||
.auto, .explicit => {
|
||||
if (enum_type.tag_ty.toType().hasRuntimeBits(mod)) return null;
|
||||
|
||||
switch (enum_type.names.len) {
|
||||
0 => return Value.@"unreachable",
|
||||
1 => {
|
||||
if (enum_type.values.len == 0) {
|
||||
const only = try mod.intern(.{ .enum_tag = .{
|
||||
.ty = ty.toIntern(),
|
||||
.int = try mod.intern(.{ .int = .{
|
||||
.ty = enum_type.tag_ty,
|
||||
.storage = .{ .u64 = 0 },
|
||||
} }),
|
||||
} });
|
||||
return only.toValue();
|
||||
} else {
|
||||
return enum_type.values[0].toValue();
|
||||
}
|
||||
},
|
||||
else => return null,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@ -2887,7 +2889,7 @@ pub const Type = struct {
|
||||
}
|
||||
|
||||
/// Asserts the type is an enum or a union.
|
||||
pub fn intTagType(ty: Type, mod: *Module) !Type {
|
||||
pub fn intTagType(ty: Type, mod: *Module) Type {
|
||||
return switch (mod.intern_pool.indexToKey(ty.toIntern())) {
|
||||
.union_type => |union_type| mod.unionPtr(union_type.index).tag_ty.intTagType(mod),
|
||||
.enum_type => |enum_type| enum_type.tag_ty.toType(),
|
||||
|
||||
@ -673,7 +673,7 @@ pub const Value = struct {
|
||||
while (true) switch (mod.intern_pool.indexToKey(check.toIntern())) {
|
||||
.ptr => |ptr| switch (ptr.addr) {
|
||||
.decl, .mut_decl, .comptime_field => return true,
|
||||
.eu_payload, .opt_payload => |index| check = index.toValue(),
|
||||
.eu_payload, .opt_payload => |base| check = base.toValue(),
|
||||
.elem, .field => |base_index| check = base_index.base.toValue(),
|
||||
else => return false,
|
||||
},
|
||||
@ -943,22 +943,27 @@ pub const Value = struct {
|
||||
return Value.true;
|
||||
}
|
||||
},
|
||||
.Int, .Enum => {
|
||||
const int_info = ty.intInfo(mod);
|
||||
.Int, .Enum => |ty_tag| {
|
||||
const int_ty = switch (ty_tag) {
|
||||
.Int => ty,
|
||||
.Enum => ty.intTagType(mod),
|
||||
else => unreachable,
|
||||
};
|
||||
const int_info = int_ty.intInfo(mod);
|
||||
const bits = int_info.bits;
|
||||
const byte_count = (bits + 7) / 8;
|
||||
if (bits == 0 or buffer.len == 0) return mod.intValue(ty, 0);
|
||||
if (bits == 0 or buffer.len == 0) return mod.getCoerced(try mod.intValue(int_ty, 0), ty);
|
||||
|
||||
if (bits <= 64) switch (int_info.signedness) { // Fast path for integers <= u64
|
||||
.signed => {
|
||||
const val = std.mem.readVarInt(i64, buffer[0..byte_count], endian);
|
||||
const result = (val << @intCast(u6, 64 - bits)) >> @intCast(u6, 64 - bits);
|
||||
return mod.intValue(ty, result);
|
||||
return mod.getCoerced(try mod.intValue(int_ty, result), ty);
|
||||
},
|
||||
.unsigned => {
|
||||
const val = std.mem.readVarInt(u64, buffer[0..byte_count], endian);
|
||||
const result = (val << @intCast(u6, 64 - bits)) >> @intCast(u6, 64 - bits);
|
||||
return mod.intValue(ty, result);
|
||||
return mod.getCoerced(try mod.intValue(int_ty, result), ty);
|
||||
},
|
||||
} else { // Slow path, we have to construct a big-int
|
||||
const Limb = std.math.big.Limb;
|
||||
@ -967,7 +972,7 @@ pub const Value = struct {
|
||||
|
||||
var bigint = BigIntMutable.init(limbs_buffer, 0);
|
||||
bigint.readTwosComplement(buffer[0..byte_count], bits, endian, int_info.signedness);
|
||||
return mod.intValue_big(ty, bigint.toConst());
|
||||
return mod.getCoerced(try mod.intValue_big(int_ty, bigint.toConst()), ty);
|
||||
}
|
||||
},
|
||||
.Float => return (try mod.intern(.{ .float = .{
|
||||
@ -1583,7 +1588,7 @@ pub const Value = struct {
|
||||
.Enum => {
|
||||
const a_val = try a.enumToInt(ty, mod);
|
||||
const b_val = try b.enumToInt(ty, mod);
|
||||
const int_ty = try ty.intTagType(mod);
|
||||
const int_ty = ty.intTagType(mod);
|
||||
return eqlAdvanced(a_val, int_ty, b_val, int_ty, mod, opt_sema);
|
||||
},
|
||||
.Array, .Vector => {
|
||||
@ -1835,7 +1840,8 @@ pub const Value = struct {
|
||||
})).toValue(),
|
||||
.ptr => |ptr| switch (ptr.addr) {
|
||||
.decl => |decl| mod.declPtr(decl).val.elemValue(mod, index),
|
||||
.mut_decl => |mut_decl| mod.declPtr(mut_decl.decl).val.elemValue(mod, index),
|
||||
.mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod))
|
||||
.toValue().elemValue(mod, index),
|
||||
.int, .eu_payload, .opt_payload => unreachable,
|
||||
.comptime_field => |field_val| field_val.toValue().elemValue(mod, index),
|
||||
.elem => |elem| elem.base.toValue().elemValue(mod, index + elem.index),
|
||||
@ -1946,9 +1952,12 @@ pub const Value = struct {
|
||||
return 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).val.sliceArray(mod, arena, start, end),
|
||||
.comptime_field => |comptime_field| try comptime_field.toValue().sliceArray(mod, arena, start, end),
|
||||
.elem => |elem| try elem.base.toValue().sliceArray(mod, arena, start + elem.index, end + elem.index),
|
||||
.mut_decl => |mut_decl| (try mod.declPtr(mut_decl.decl).internValue(mod)).toValue()
|
||||
.sliceArray(mod, arena, start, end),
|
||||
.comptime_field => |comptime_field| comptime_field.toValue()
|
||||
.sliceArray(mod, arena, start, end),
|
||||
.elem => |elem| elem.base.toValue()
|
||||
.sliceArray(mod, arena, start + elem.index, end + elem.index),
|
||||
else => unreachable,
|
||||
},
|
||||
.aggregate => |aggregate| (try mod.intern(.{ .aggregate = .{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user