mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Replace uses of Value.zero, Value.one, Value.negative_one
This is a bit nasty, mainly because Type.onePossibleValue is now errorable, which is a quite viral change.
This commit is contained in:
parent
4c3c605e5f
commit
2ffef605c7
16 changed files with 286 additions and 223 deletions
|
|
@ -1485,7 +1485,7 @@ pub fn refToIndexAllowNone(inst: Inst.Ref) ?Inst.Index {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `null` if runtime-known.
|
/// Returns `null` if runtime-known.
|
||||||
pub fn value(air: Air, inst: Inst.Ref, mod: *const Module) ?Value {
|
pub fn value(air: Air, inst: Inst.Ref, mod: *Module) !?Value {
|
||||||
const ref_int = @enumToInt(inst);
|
const ref_int = @enumToInt(inst);
|
||||||
if (ref_int < ref_start_index) {
|
if (ref_int < ref_start_index) {
|
||||||
const ip_index = @intToEnum(InternPool.Index, ref_int);
|
const ip_index = @intToEnum(InternPool.Index, ref_int);
|
||||||
|
|
|
||||||
|
|
@ -5750,7 +5750,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air {
|
||||||
|
|
||||||
const arg_val = if (!arg_tv.val.isGenericPoison())
|
const arg_val = if (!arg_tv.val.isGenericPoison())
|
||||||
arg_tv.val
|
arg_tv.val
|
||||||
else if (arg_tv.ty.onePossibleValue(mod)) |opv|
|
else if (try arg_tv.ty.onePossibleValue(mod)) |opv|
|
||||||
opv
|
opv
|
||||||
else
|
else
|
||||||
break :t arg_tv.ty;
|
break :t arg_tv.ty;
|
||||||
|
|
@ -6887,6 +6887,16 @@ pub fn singleConstPtrType(mod: *Module, child_type: Type) Allocator.Error!Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intValue(mod: *Module, ty: Type, x: anytype) Allocator.Error!Value {
|
pub fn intValue(mod: *Module, ty: Type, x: anytype) Allocator.Error!Value {
|
||||||
|
if (std.debug.runtime_safety) {
|
||||||
|
// TODO: decide if this also works for ABI int types like enums
|
||||||
|
const tag = ty.zigTypeTag(mod);
|
||||||
|
assert(tag == .Int or tag == .ComptimeInt);
|
||||||
|
}
|
||||||
|
if (@TypeOf(x) == comptime_int) {
|
||||||
|
if (comptime std.math.cast(u64, x)) |casted| return intValue_u64(mod, ty, casted);
|
||||||
|
if (comptime std.math.cast(i64, x)) |casted| return intValue_i64(mod, ty, casted);
|
||||||
|
@compileError("Out-of-range comptime_int passed to Module.intValue");
|
||||||
|
}
|
||||||
if (std.math.cast(u64, x)) |casted| return intValue_u64(mod, ty, casted);
|
if (std.math.cast(u64, x)) |casted| return intValue_u64(mod, ty, casted);
|
||||||
if (std.math.cast(i64, x)) |casted| return intValue_i64(mod, ty, casted);
|
if (std.math.cast(i64, x)) |casted| return intValue_i64(mod, ty, casted);
|
||||||
var limbs_buffer: [4]usize = undefined;
|
var limbs_buffer: [4]usize = undefined;
|
||||||
|
|
|
||||||
257
src/Sema.zig
257
src/Sema.zig
|
|
@ -3062,9 +3062,9 @@ fn zirEnumDecl(
|
||||||
}
|
}
|
||||||
} else if (any_values) {
|
} else if (any_values) {
|
||||||
const tag_val = if (last_tag_val) |val|
|
const tag_val = if (last_tag_val) |val|
|
||||||
try sema.intAdd(val, Value.one, enum_obj.tag_ty)
|
try sema.intAdd(val, try mod.intValue(enum_obj.tag_ty, 1), enum_obj.tag_ty)
|
||||||
else
|
else
|
||||||
Value.zero;
|
try mod.intValue(enum_obj.tag_ty, 0);
|
||||||
last_tag_val = tag_val;
|
last_tag_val = tag_val;
|
||||||
const copied_tag_val = try tag_val.copy(decl_arena_allocator);
|
const copied_tag_val = try tag_val.copy(decl_arena_allocator);
|
||||||
const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{
|
const gop_val = enum_obj.values.getOrPutAssumeCapacityContext(copied_tag_val, .{
|
||||||
|
|
@ -4709,7 +4709,7 @@ fn zirValidateArrayInit(
|
||||||
// Determine whether the value stored to this pointer is comptime-known.
|
// Determine whether the value stored to this pointer is comptime-known.
|
||||||
|
|
||||||
if (array_ty.isTuple()) {
|
if (array_ty.isTuple()) {
|
||||||
if (array_ty.structFieldValueComptime(mod, i)) |opv| {
|
if (try array_ty.structFieldValueComptime(mod, i)) |opv| {
|
||||||
element_vals[i] = opv;
|
element_vals[i] = opv;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -8132,7 +8132,7 @@ fn zirErrorToInt(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
|
||||||
if (!op_ty.isAnyError()) {
|
if (!op_ty.isAnyError()) {
|
||||||
const names = op_ty.errorSetNames();
|
const names = op_ty.errorSetNames();
|
||||||
switch (names.len) {
|
switch (names.len) {
|
||||||
0 => return sema.addConstant(Type.err_int, Value.zero),
|
0 => return sema.addConstant(Type.err_int, try mod.intValue(Type.err_int, 0)),
|
||||||
1 => return sema.addIntUnsigned(Type.err_int, sema.mod.global_error_set.get(names[0]).?),
|
1 => return sema.addIntUnsigned(Type.err_int, sema.mod.global_error_set.get(names[0]).?),
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
|
@ -8167,7 +8167,7 @@ fn zirIntToError(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDat
|
||||||
try sema.requireRuntimeBlock(block, src, operand_src);
|
try sema.requireRuntimeBlock(block, src, operand_src);
|
||||||
if (block.wantSafety()) {
|
if (block.wantSafety()) {
|
||||||
const is_lt_len = try block.addUnOp(.cmp_lt_errors_len, operand);
|
const is_lt_len = try block.addUnOp(.cmp_lt_errors_len, operand);
|
||||||
const zero_val = try sema.addConstant(Type.err_int, Value.zero);
|
const zero_val = try sema.addConstant(Type.err_int, try mod.intValue(Type.err_int, 0));
|
||||||
const is_non_zero = try block.addBinOp(.cmp_neq, operand, zero_val);
|
const is_non_zero = try block.addBinOp(.cmp_neq, operand, zero_val);
|
||||||
const ok = try block.addBinOp(.bit_and, is_lt_len, is_non_zero);
|
const ok = try block.addBinOp(.bit_and, is_lt_len, is_non_zero);
|
||||||
try sema.addSafetyCheck(block, ok, .invalid_error_code);
|
try sema.addSafetyCheck(block, ok, .invalid_error_code);
|
||||||
|
|
@ -9656,7 +9656,7 @@ fn intCast(
|
||||||
|
|
||||||
if (wanted_bits == 0) {
|
if (wanted_bits == 0) {
|
||||||
const ok = if (is_vector) ok: {
|
const ok = if (is_vector) ok: {
|
||||||
const zeros = try Value.Tag.repeated.create(sema.arena, Value.zero);
|
const zeros = try Value.Tag.repeated.create(sema.arena, try mod.intValue(operand_scalar_ty, 0));
|
||||||
const zero_inst = try sema.addConstant(sema.typeOf(operand), zeros);
|
const zero_inst = try sema.addConstant(sema.typeOf(operand), zeros);
|
||||||
const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);
|
const is_in_range = try block.addCmpVector(operand, zero_inst, .eq);
|
||||||
const all_in_range = try block.addInst(.{
|
const all_in_range = try block.addInst(.{
|
||||||
|
|
@ -9665,7 +9665,7 @@ fn intCast(
|
||||||
});
|
});
|
||||||
break :ok all_in_range;
|
break :ok all_in_range;
|
||||||
} else ok: {
|
} else ok: {
|
||||||
const zero_inst = try sema.addConstant(sema.typeOf(operand), Value.zero);
|
const zero_inst = try sema.addConstant(sema.typeOf(operand), try mod.intValue(operand_ty, 0));
|
||||||
const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst);
|
const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst);
|
||||||
break :ok is_in_range;
|
break :ok is_in_range;
|
||||||
};
|
};
|
||||||
|
|
@ -9705,8 +9705,9 @@ fn intCast(
|
||||||
// If the destination type is signed, then we need to double its
|
// If the destination type is signed, then we need to double its
|
||||||
// range to account for negative values.
|
// range to account for negative values.
|
||||||
const dest_range_val = if (wanted_info.signedness == .signed) range_val: {
|
const dest_range_val = if (wanted_info.signedness == .signed) range_val: {
|
||||||
const range_minus_one = try dest_max_val.shl(Value.one, unsigned_operand_ty, sema.arena, sema.mod);
|
const one = try mod.intValue(unsigned_operand_ty, 1);
|
||||||
break :range_val try sema.intAdd(range_minus_one, Value.one, unsigned_operand_ty);
|
const range_minus_one = try dest_max_val.shl(one, unsigned_operand_ty, sema.arena, sema.mod);
|
||||||
|
break :range_val try sema.intAdd(range_minus_one, one, unsigned_operand_ty);
|
||||||
} else dest_max_val;
|
} else dest_max_val;
|
||||||
const dest_range = try sema.addConstant(unsigned_operand_ty, dest_range_val);
|
const dest_range = try sema.addConstant(unsigned_operand_ty, dest_range_val);
|
||||||
|
|
||||||
|
|
@ -9747,7 +9748,7 @@ fn intCast(
|
||||||
// no shrinkage, yes sign loss
|
// no shrinkage, yes sign loss
|
||||||
// requirement: signed to unsigned >= 0
|
// requirement: signed to unsigned >= 0
|
||||||
const ok = if (is_vector) ok: {
|
const ok = if (is_vector) ok: {
|
||||||
const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
|
const zero_val = try Value.Tag.repeated.create(sema.arena, try mod.intValue(operand_scalar_ty, 0));
|
||||||
const zero_inst = try sema.addConstant(operand_ty, zero_val);
|
const zero_inst = try sema.addConstant(operand_ty, zero_val);
|
||||||
const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);
|
const is_in_range = try block.addCmpVector(operand, zero_inst, .gte);
|
||||||
const all_in_range = try block.addInst(.{
|
const all_in_range = try block.addInst(.{
|
||||||
|
|
@ -9759,7 +9760,7 @@ fn intCast(
|
||||||
});
|
});
|
||||||
break :ok all_in_range;
|
break :ok all_in_range;
|
||||||
} else ok: {
|
} else ok: {
|
||||||
const zero_inst = try sema.addConstant(operand_ty, Value.zero);
|
const zero_inst = try sema.addConstant(operand_ty, try mod.intValue(operand_ty, 0));
|
||||||
const is_in_range = try block.addBinOp(.cmp_gte, operand, zero_inst);
|
const is_in_range = try block.addBinOp(.cmp_gte, operand, zero_inst);
|
||||||
break :ok is_in_range;
|
break :ok is_in_range;
|
||||||
};
|
};
|
||||||
|
|
@ -11250,7 +11251,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
|
||||||
|
|
||||||
while (item.compareScalar(.lte, item_last, operand_ty, mod)) : ({
|
while (item.compareScalar(.lte, item_last, operand_ty, mod)) : ({
|
||||||
// Previous validation has resolved any possible lazy values.
|
// Previous validation has resolved any possible lazy values.
|
||||||
item = try sema.intAddScalar(item, Value.one, operand_ty);
|
item = try sema.intAddScalar(item, try mod.intValue(operand_ty, 1), operand_ty);
|
||||||
}) {
|
}) {
|
||||||
cases_len += 1;
|
cases_len += 1;
|
||||||
|
|
||||||
|
|
@ -11696,7 +11697,7 @@ const RangeSetUnhandledIterator = struct {
|
||||||
fn next(it: *RangeSetUnhandledIterator) !?Value {
|
fn next(it: *RangeSetUnhandledIterator) !?Value {
|
||||||
while (it.range_i < it.ranges.len) : (it.range_i += 1) {
|
while (it.range_i < it.ranges.len) : (it.range_i += 1) {
|
||||||
if (!it.first) {
|
if (!it.first) {
|
||||||
it.cur = try it.sema.intAddScalar(it.cur, Value.one, it.ty);
|
it.cur = try it.sema.intAddScalar(it.cur, try it.sema.mod.intValue(it.ty, 1), it.ty);
|
||||||
}
|
}
|
||||||
it.first = false;
|
it.first = false;
|
||||||
if (it.cur.compareScalar(.lt, it.ranges[it.range_i].first, it.ty, it.sema.mod)) {
|
if (it.cur.compareScalar(.lt, it.ranges[it.range_i].first, it.ty, it.sema.mod)) {
|
||||||
|
|
@ -11705,7 +11706,7 @@ const RangeSetUnhandledIterator = struct {
|
||||||
it.cur = it.ranges[it.range_i].last;
|
it.cur = it.ranges[it.range_i].last;
|
||||||
}
|
}
|
||||||
if (!it.first) {
|
if (!it.first) {
|
||||||
it.cur = try it.sema.intAddScalar(it.cur, Value.one, it.ty);
|
it.cur = try it.sema.intAddScalar(it.cur, try it.sema.mod.intValue(it.ty, 1), it.ty);
|
||||||
}
|
}
|
||||||
it.first = false;
|
it.first = false;
|
||||||
if (it.cur.compareScalar(.lte, it.max, it.ty, it.sema.mod)) {
|
if (it.cur.compareScalar(.lte, it.max, it.ty, it.sema.mod)) {
|
||||||
|
|
@ -12150,7 +12151,7 @@ fn zirEmbedFile(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||||
// into the final binary, and never loads the data into memory.
|
// into the final binary, and never loads the data into memory.
|
||||||
// - When a Decl is destroyed, it can free the `*Module.EmbedFile`.
|
// - When a Decl is destroyed, it can free the `*Module.EmbedFile`.
|
||||||
embed_file.owner_decl = try anon_decl.finish(
|
embed_file.owner_decl = try anon_decl.finish(
|
||||||
try Type.array(anon_decl.arena(), embed_file.bytes.len, Value.zero, Type.u8, mod),
|
try Type.array(anon_decl.arena(), embed_file.bytes.len, try mod.intValue(Type.u8, 0), Type.u8, mod),
|
||||||
try Value.Tag.bytes.create(anon_decl.arena(), bytes_including_null),
|
try Value.Tag.bytes.create(anon_decl.arena(), bytes_including_null),
|
||||||
0, // default alignment
|
0, // default alignment
|
||||||
);
|
);
|
||||||
|
|
@ -12235,14 +12236,14 @@ fn zirShl(
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < rhs_ty.vectorLen(mod)) : (i += 1) {
|
while (i < rhs_ty.vectorLen(mod)) : (i += 1) {
|
||||||
const rhs_elem = try rhs_val.elemValue(sema.mod, i);
|
const rhs_elem = try rhs_val.elemValue(sema.mod, i);
|
||||||
if (rhs_elem.compareHetero(.lt, Value.zero, mod)) {
|
if (rhs_elem.compareHetero(.lt, try mod.intValue(scalar_rhs_ty, 0), mod)) {
|
||||||
return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{
|
return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{
|
||||||
rhs_elem.fmtValue(scalar_ty, sema.mod),
|
rhs_elem.fmtValue(scalar_ty, sema.mod),
|
||||||
i,
|
i,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (rhs_val.compareHetero(.lt, Value.zero, mod)) {
|
} else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) {
|
||||||
return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{
|
return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{
|
||||||
rhs_val.fmtValue(scalar_ty, sema.mod),
|
rhs_val.fmtValue(scalar_ty, sema.mod),
|
||||||
});
|
});
|
||||||
|
|
@ -12348,7 +12349,7 @@ fn zirShl(
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
ov_bit;
|
ov_bit;
|
||||||
const zero_ov = try sema.addConstant(Type.u1, Value.zero);
|
const zero_ov = try sema.addConstant(Type.u1, try mod.intValue(Type.u1, 0));
|
||||||
const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov);
|
const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov);
|
||||||
|
|
||||||
try sema.addSafetyCheck(block, no_ov, .shl_overflow);
|
try sema.addSafetyCheck(block, no_ov, .shl_overflow);
|
||||||
|
|
@ -12417,14 +12418,14 @@ fn zirShr(
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < rhs_ty.vectorLen(mod)) : (i += 1) {
|
while (i < rhs_ty.vectorLen(mod)) : (i += 1) {
|
||||||
const rhs_elem = try rhs_val.elemValue(sema.mod, i);
|
const rhs_elem = try rhs_val.elemValue(sema.mod, i);
|
||||||
if (rhs_elem.compareHetero(.lt, Value.zero, mod)) {
|
if (rhs_elem.compareHetero(.lt, try mod.intValue(rhs_ty.childType(mod), 0), mod)) {
|
||||||
return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{
|
return sema.fail(block, rhs_src, "shift by negative amount '{}' at index '{d}'", .{
|
||||||
rhs_elem.fmtValue(scalar_ty, sema.mod),
|
rhs_elem.fmtValue(scalar_ty, sema.mod),
|
||||||
i,
|
i,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (rhs_val.compareHetero(.lt, Value.zero, mod)) {
|
} else if (rhs_val.compareHetero(.lt, try mod.intValue(rhs_ty, 0), mod)) {
|
||||||
return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{
|
return sema.fail(block, rhs_src, "shift by negative amount '{}'", .{
|
||||||
rhs_val.fmtValue(scalar_ty, sema.mod),
|
rhs_val.fmtValue(scalar_ty, sema.mod),
|
||||||
});
|
});
|
||||||
|
|
@ -13156,9 +13157,9 @@ fn zirNegate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
|
||||||
}
|
}
|
||||||
|
|
||||||
const lhs = if (rhs_ty.zigTypeTag(mod) == .Vector)
|
const lhs = if (rhs_ty.zigTypeTag(mod) == .Vector)
|
||||||
try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero))
|
try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, try mod.intValue(rhs_scalar_ty, 0)))
|
||||||
else
|
else
|
||||||
try sema.resolveInst(.zero);
|
try sema.addConstant(rhs_ty, try mod.intValue(rhs_ty, 0));
|
||||||
|
|
||||||
return sema.analyzeArithmetic(block, .sub, lhs, rhs, src, lhs_src, rhs_src, true);
|
return sema.analyzeArithmetic(block, .sub, lhs, rhs, src, lhs_src, rhs_src, true);
|
||||||
}
|
}
|
||||||
|
|
@ -13180,9 +13181,9 @@ fn zirNegateWrap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
|
||||||
}
|
}
|
||||||
|
|
||||||
const lhs = if (rhs_ty.zigTypeTag(mod) == .Vector)
|
const lhs = if (rhs_ty.zigTypeTag(mod) == .Vector)
|
||||||
try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, Value.zero))
|
try sema.addConstant(rhs_ty, try Value.Tag.repeated.create(sema.arena, try mod.intValue(rhs_scalar_ty, 0)))
|
||||||
else
|
else
|
||||||
try sema.resolveInst(.zero);
|
try sema.addConstant(rhs_ty, try mod.intValue(rhs_ty, 0));
|
||||||
|
|
||||||
return sema.analyzeArithmetic(block, .subwrap, lhs, rhs, src, lhs_src, rhs_src, true);
|
return sema.analyzeArithmetic(block, .subwrap, lhs, rhs, src, lhs_src, rhs_src, true);
|
||||||
}
|
}
|
||||||
|
|
@ -13293,9 +13294,14 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (!lhs_val.isUndef()) {
|
if (!lhs_val.isUndef()) {
|
||||||
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||||
|
const scalar_zero = switch (scalar_tag) {
|
||||||
|
.ComptimeFloat, .Float => Value.float_zero, // TODO migrate to internpool
|
||||||
|
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
const zero_val = if (is_vector) b: {
|
const zero_val = if (is_vector) b: {
|
||||||
break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
|
break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
} else Value.zero;
|
} else scalar_zero;
|
||||||
return sema.addConstant(resolved_type, zero_val);
|
return sema.addConstant(resolved_type, zero_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13318,7 +13324,7 @@ fn zirDiv(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Ins
|
||||||
if (lhs_val.isUndef()) {
|
if (lhs_val.isUndef()) {
|
||||||
if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) {
|
if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) {
|
||||||
if (maybe_rhs_val) |rhs_val| {
|
if (maybe_rhs_val) |rhs_val| {
|
||||||
if (try sema.compareAll(rhs_val, .neq, Value.negative_one, resolved_type)) {
|
if (try sema.compareAll(rhs_val, .neq, try mod.intValue(resolved_type, -1), resolved_type)) {
|
||||||
return sema.addConstUndef(resolved_type);
|
return sema.addConstUndef(resolved_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13427,9 +13433,14 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
return sema.failWithUseOfUndef(block, rhs_src);
|
return sema.failWithUseOfUndef(block, rhs_src);
|
||||||
} else {
|
} else {
|
||||||
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||||
|
const scalar_zero = switch (scalar_tag) {
|
||||||
|
.ComptimeFloat, .Float => Value.float_zero, // TODO migrate to internpool
|
||||||
|
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
const zero_val = if (is_vector) b: {
|
const zero_val = if (is_vector) b: {
|
||||||
break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
|
break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
} else Value.zero;
|
} else scalar_zero;
|
||||||
return sema.addConstant(resolved_type, zero_val);
|
return sema.addConstant(resolved_type, zero_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13507,8 +13518,13 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
} else ok: {
|
} else ok: {
|
||||||
const remainder = try block.addBinOp(.rem, casted_lhs, casted_rhs);
|
const remainder = try block.addBinOp(.rem, casted_lhs, casted_rhs);
|
||||||
|
|
||||||
|
const scalar_zero = switch (scalar_tag) {
|
||||||
|
.ComptimeFloat, .Float => Value.float_zero, // TODO migrate to internpool
|
||||||
|
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
if (resolved_type.zigTypeTag(mod) == .Vector) {
|
if (resolved_type.zigTypeTag(mod) == .Vector) {
|
||||||
const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
|
const zero_val = try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
const zero = try sema.addConstant(resolved_type, zero_val);
|
const zero = try sema.addConstant(resolved_type, zero_val);
|
||||||
const eql = try block.addCmpVector(remainder, zero, .eq);
|
const eql = try block.addCmpVector(remainder, zero, .eq);
|
||||||
break :ok try block.addInst(.{
|
break :ok try block.addInst(.{
|
||||||
|
|
@ -13519,7 +13535,7 @@ fn zirDivExact(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
} },
|
} },
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const zero = try sema.addConstant(resolved_type, Value.zero);
|
const zero = try sema.addConstant(resolved_type, scalar_zero);
|
||||||
const is_in_range = try block.addBinOp(.cmp_eq, remainder, zero);
|
const is_in_range = try block.addBinOp(.cmp_eq, remainder, zero);
|
||||||
break :ok is_in_range;
|
break :ok is_in_range;
|
||||||
}
|
}
|
||||||
|
|
@ -13592,9 +13608,14 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (!lhs_val.isUndef()) {
|
if (!lhs_val.isUndef()) {
|
||||||
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||||
|
const scalar_zero = switch (scalar_tag) {
|
||||||
|
.ComptimeFloat, .Float => Value.float_zero, // TODO migrate to internpool
|
||||||
|
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
const zero_val = if (is_vector) b: {
|
const zero_val = if (is_vector) b: {
|
||||||
break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
|
break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
} else Value.zero;
|
} else scalar_zero;
|
||||||
return sema.addConstant(resolved_type, zero_val);
|
return sema.addConstant(resolved_type, zero_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13612,7 +13633,7 @@ fn zirDivFloor(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
if (lhs_val.isUndef()) {
|
if (lhs_val.isUndef()) {
|
||||||
if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) {
|
if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) {
|
||||||
if (maybe_rhs_val) |rhs_val| {
|
if (maybe_rhs_val) |rhs_val| {
|
||||||
if (try sema.compareAll(rhs_val, .neq, Value.negative_one, resolved_type)) {
|
if (try sema.compareAll(rhs_val, .neq, try mod.intValue(resolved_type, -1), resolved_type)) {
|
||||||
return sema.addConstUndef(resolved_type);
|
return sema.addConstUndef(resolved_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13708,9 +13729,14 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (!lhs_val.isUndef()) {
|
if (!lhs_val.isUndef()) {
|
||||||
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||||
|
const scalar_zero = switch (scalar_tag) {
|
||||||
|
.ComptimeFloat, .Float => Value.float_zero, // TODO migrate to internpool
|
||||||
|
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
const zero_val = if (is_vector) b: {
|
const zero_val = if (is_vector) b: {
|
||||||
break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
|
break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
} else Value.zero;
|
} else scalar_zero;
|
||||||
return sema.addConstant(resolved_type, zero_val);
|
return sema.addConstant(resolved_type, zero_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13727,7 +13753,7 @@ fn zirDivTrunc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
if (lhs_val.isUndef()) {
|
if (lhs_val.isUndef()) {
|
||||||
if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) {
|
if (lhs_scalar_ty.isSignedInt(mod) and rhs_scalar_ty.isSignedInt(mod)) {
|
||||||
if (maybe_rhs_val) |rhs_val| {
|
if (maybe_rhs_val) |rhs_val| {
|
||||||
if (try sema.compareAll(rhs_val, .neq, Value.negative_one, resolved_type)) {
|
if (try sema.compareAll(rhs_val, .neq, try mod.intValue(resolved_type, -1), resolved_type)) {
|
||||||
return sema.addConstUndef(resolved_type);
|
return sema.addConstUndef(resolved_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -13862,8 +13888,9 @@ fn addDivByZeroSafety(
|
||||||
if (maybe_rhs_val != null) return;
|
if (maybe_rhs_val != null) return;
|
||||||
|
|
||||||
const mod = sema.mod;
|
const mod = sema.mod;
|
||||||
|
const scalar_zero = if (is_int) try mod.intValue(resolved_type.scalarType(mod), 0) else Value.float_zero; // TODO migrate to internpool
|
||||||
const ok = if (resolved_type.zigTypeTag(mod) == .Vector) ok: {
|
const ok = if (resolved_type.zigTypeTag(mod) == .Vector) ok: {
|
||||||
const zero_val = try Value.Tag.repeated.create(sema.arena, Value.zero);
|
const zero_val = try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
const zero = try sema.addConstant(resolved_type, zero_val);
|
const zero = try sema.addConstant(resolved_type, zero_val);
|
||||||
const ok = try block.addCmpVector(casted_rhs, zero, .neq);
|
const ok = try block.addCmpVector(casted_rhs, zero, .neq);
|
||||||
break :ok try block.addInst(.{
|
break :ok try block.addInst(.{
|
||||||
|
|
@ -13874,7 +13901,7 @@ fn addDivByZeroSafety(
|
||||||
} },
|
} },
|
||||||
});
|
});
|
||||||
} else ok: {
|
} else ok: {
|
||||||
const zero = try sema.addConstant(resolved_type, Value.zero);
|
const zero = try sema.addConstant(resolved_type, scalar_zero);
|
||||||
break :ok try block.addBinOp(if (is_int) .cmp_neq else .cmp_neq_optimized, casted_rhs, zero);
|
break :ok try block.addBinOp(if (is_int) .cmp_neq else .cmp_neq_optimized, casted_rhs, zero);
|
||||||
};
|
};
|
||||||
try sema.addSafetyCheck(block, ok, .divide_by_zero);
|
try sema.addSafetyCheck(block, ok, .divide_by_zero);
|
||||||
|
|
@ -13946,9 +13973,14 @@ fn zirModRem(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
|
||||||
return sema.failWithUseOfUndef(block, lhs_src);
|
return sema.failWithUseOfUndef(block, lhs_src);
|
||||||
}
|
}
|
||||||
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||||
|
const scalar_zero = switch (scalar_tag) {
|
||||||
|
.ComptimeFloat, .Float => Value.float_zero, // TODO migrate to internpool
|
||||||
|
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
const zero_val = if (is_vector) b: {
|
const zero_val = if (is_vector) b: {
|
||||||
break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
|
break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
} else Value.zero;
|
} else scalar_zero;
|
||||||
return sema.addConstant(resolved_type, zero_val);
|
return sema.addConstant(resolved_type, zero_val);
|
||||||
}
|
}
|
||||||
} else if (lhs_scalar_ty.isSignedInt(mod)) {
|
} else if (lhs_scalar_ty.isSignedInt(mod)) {
|
||||||
|
|
@ -14325,6 +14357,7 @@ fn zirOverflowArithmetic(
|
||||||
wrapped: Value = Value.@"unreachable",
|
wrapped: Value = Value.@"unreachable",
|
||||||
overflow_bit: Value,
|
overflow_bit: Value,
|
||||||
} = result: {
|
} = result: {
|
||||||
|
const zero = try mod.intValue(dest_ty.scalarType(mod), 0);
|
||||||
switch (zir_tag) {
|
switch (zir_tag) {
|
||||||
.add_with_overflow => {
|
.add_with_overflow => {
|
||||||
// If either of the arguments is zero, `false` is returned and the other is stored
|
// If either of the arguments is zero, `false` is returned and the other is stored
|
||||||
|
|
@ -14332,12 +14365,12 @@ fn zirOverflowArithmetic(
|
||||||
// Otherwise, if either of the argument is undefined, undefined is returned.
|
// Otherwise, if either of the argument is undefined, undefined is returned.
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
|
if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
|
||||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = rhs };
|
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = rhs };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (maybe_rhs_val) |rhs_val| {
|
if (maybe_rhs_val) |rhs_val| {
|
||||||
if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
|
if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
|
||||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
|
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
|
|
@ -14358,7 +14391,7 @@ fn zirOverflowArithmetic(
|
||||||
if (rhs_val.isUndef()) {
|
if (rhs_val.isUndef()) {
|
||||||
break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
|
break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
|
||||||
} else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
} else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
|
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
|
||||||
} else if (maybe_lhs_val) |lhs_val| {
|
} else if (maybe_lhs_val) |lhs_val| {
|
||||||
if (lhs_val.isUndef()) {
|
if (lhs_val.isUndef()) {
|
||||||
break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
|
break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
|
||||||
|
|
@ -14373,12 +14406,13 @@ fn zirOverflowArithmetic(
|
||||||
// If either of the arguments is zero, the result is zero and no overflow occured.
|
// If either of the arguments is zero, the result is zero and no overflow occured.
|
||||||
// If either of the arguments is one, the result is the other and no overflow occured.
|
// If either of the arguments is one, the result is the other and no overflow occured.
|
||||||
// Otherwise, if either of the arguments is undefined, both results are undefined.
|
// Otherwise, if either of the arguments is undefined, both results are undefined.
|
||||||
|
const scalar_one = try mod.intValue(dest_ty.scalarType(mod), 1);
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (!lhs_val.isUndef()) {
|
if (!lhs_val.isUndef()) {
|
||||||
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
|
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
|
||||||
} else if (try sema.compareAll(lhs_val, .eq, try maybeRepeated(sema, dest_ty, Value.one), dest_ty)) {
|
} else if (try sema.compareAll(lhs_val, .eq, try maybeRepeated(sema, dest_ty, scalar_one), dest_ty)) {
|
||||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = rhs };
|
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = rhs };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14386,9 +14420,9 @@ fn zirOverflowArithmetic(
|
||||||
if (maybe_rhs_val) |rhs_val| {
|
if (maybe_rhs_val) |rhs_val| {
|
||||||
if (!rhs_val.isUndef()) {
|
if (!rhs_val.isUndef()) {
|
||||||
if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = rhs };
|
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = rhs };
|
||||||
} else if (try sema.compareAll(rhs_val, .eq, try maybeRepeated(sema, dest_ty, Value.one), dest_ty)) {
|
} else if (try sema.compareAll(rhs_val, .eq, try maybeRepeated(sema, dest_ty, scalar_one), dest_ty)) {
|
||||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
|
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14410,12 +14444,12 @@ fn zirOverflowArithmetic(
|
||||||
// Oterhwise if either of the arguments is undefined, both results are undefined.
|
// Oterhwise if either of the arguments is undefined, both results are undefined.
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
|
if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
|
||||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
|
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (maybe_rhs_val) |rhs_val| {
|
if (maybe_rhs_val) |rhs_val| {
|
||||||
if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
|
if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
|
||||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
|
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, zero), .inst = lhs };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
|
|
@ -14766,6 +14800,11 @@ fn analyzeArithmetic(
|
||||||
// If either of the operands are inf, and the other operand is zero,
|
// If either of the operands are inf, and the other operand is zero,
|
||||||
// the result is nan.
|
// the result is nan.
|
||||||
// If either of the operands are nan, the result is nan.
|
// If either of the operands are nan, the result is nan.
|
||||||
|
const scalar_zero = switch (scalar_tag) {
|
||||||
|
.ComptimeFloat, .Float => Value.float_zero, // TODO migrate to internpool
|
||||||
|
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (!lhs_val.isUndef()) {
|
if (!lhs_val.isUndef()) {
|
||||||
if (lhs_val.isNan()) {
|
if (lhs_val.isNan()) {
|
||||||
|
|
@ -14783,11 +14822,11 @@ fn analyzeArithmetic(
|
||||||
break :lz;
|
break :lz;
|
||||||
}
|
}
|
||||||
const zero_val = if (is_vector) b: {
|
const zero_val = if (is_vector) b: {
|
||||||
break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
|
break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
} else Value.zero;
|
} else scalar_zero;
|
||||||
return sema.addConstant(resolved_type, zero_val);
|
return sema.addConstant(resolved_type, zero_val);
|
||||||
}
|
}
|
||||||
if (try sema.compareAll(lhs_val, .eq, Value.one, resolved_type)) {
|
if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
|
||||||
return casted_rhs;
|
return casted_rhs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14813,11 +14852,11 @@ fn analyzeArithmetic(
|
||||||
break :rz;
|
break :rz;
|
||||||
}
|
}
|
||||||
const zero_val = if (is_vector) b: {
|
const zero_val = if (is_vector) b: {
|
||||||
break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
|
break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
} else Value.zero;
|
} else scalar_zero;
|
||||||
return sema.addConstant(resolved_type, zero_val);
|
return sema.addConstant(resolved_type, zero_val);
|
||||||
}
|
}
|
||||||
if (try sema.compareAll(rhs_val, .eq, Value.one, resolved_type)) {
|
if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
|
||||||
return casted_lhs;
|
return casted_lhs;
|
||||||
}
|
}
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
|
|
@ -14849,15 +14888,20 @@ fn analyzeArithmetic(
|
||||||
// If either of the operands are zero, result is zero.
|
// If either of the operands are zero, result is zero.
|
||||||
// If either of the operands are one, result is the other operand.
|
// If either of the operands are one, result is the other operand.
|
||||||
// If either of the operands are undefined, result is undefined.
|
// If either of the operands are undefined, result is undefined.
|
||||||
|
const scalar_zero = switch (scalar_tag) {
|
||||||
|
.ComptimeFloat, .Float => Value.float_zero, // TODO migrate to internpool
|
||||||
|
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (!lhs_val.isUndef()) {
|
if (!lhs_val.isUndef()) {
|
||||||
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||||
const zero_val = if (is_vector) b: {
|
const zero_val = if (is_vector) b: {
|
||||||
break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
|
break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
} else Value.zero;
|
} else scalar_zero;
|
||||||
return sema.addConstant(resolved_type, zero_val);
|
return sema.addConstant(resolved_type, zero_val);
|
||||||
}
|
}
|
||||||
if (try sema.compareAll(lhs_val, .eq, Value.one, resolved_type)) {
|
if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
|
||||||
return casted_rhs;
|
return casted_rhs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14869,11 +14913,11 @@ fn analyzeArithmetic(
|
||||||
}
|
}
|
||||||
if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||||
const zero_val = if (is_vector) b: {
|
const zero_val = if (is_vector) b: {
|
||||||
break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
|
break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
} else Value.zero;
|
} else scalar_zero;
|
||||||
return sema.addConstant(resolved_type, zero_val);
|
return sema.addConstant(resolved_type, zero_val);
|
||||||
}
|
}
|
||||||
if (try sema.compareAll(rhs_val, .eq, Value.one, resolved_type)) {
|
if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
|
||||||
return casted_lhs;
|
return casted_lhs;
|
||||||
}
|
}
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
|
|
@ -14892,15 +14936,20 @@ fn analyzeArithmetic(
|
||||||
// If either of the operands are zero, result is zero.
|
// If either of the operands are zero, result is zero.
|
||||||
// If either of the operands are one, result is the other operand.
|
// If either of the operands are one, result is the other operand.
|
||||||
// If either of the operands are undefined, result is undefined.
|
// If either of the operands are undefined, result is undefined.
|
||||||
|
const scalar_zero = switch (scalar_tag) {
|
||||||
|
.ComptimeFloat, .Float => Value.float_zero, // TODO migrate to internpool
|
||||||
|
.ComptimeInt, .Int => try mod.intValue(resolved_type.scalarType(mod), 0),
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
if (!lhs_val.isUndef()) {
|
if (!lhs_val.isUndef()) {
|
||||||
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||||
const zero_val = if (is_vector) b: {
|
const zero_val = if (is_vector) b: {
|
||||||
break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
|
break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
} else Value.zero;
|
} else scalar_zero;
|
||||||
return sema.addConstant(resolved_type, zero_val);
|
return sema.addConstant(resolved_type, zero_val);
|
||||||
}
|
}
|
||||||
if (try sema.compareAll(lhs_val, .eq, Value.one, resolved_type)) {
|
if (try sema.compareAll(lhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
|
||||||
return casted_rhs;
|
return casted_rhs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14911,11 +14960,11 @@ fn analyzeArithmetic(
|
||||||
}
|
}
|
||||||
if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||||
const zero_val = if (is_vector) b: {
|
const zero_val = if (is_vector) b: {
|
||||||
break :b try Value.Tag.repeated.create(sema.arena, Value.zero);
|
break :b try Value.Tag.repeated.create(sema.arena, scalar_zero);
|
||||||
} else Value.zero;
|
} else scalar_zero;
|
||||||
return sema.addConstant(resolved_type, zero_val);
|
return sema.addConstant(resolved_type, zero_val);
|
||||||
}
|
}
|
||||||
if (try sema.compareAll(rhs_val, .eq, Value.one, resolved_type)) {
|
if (try sema.compareAll(rhs_val, .eq, try mod.intValue(resolved_type, 1), resolved_type)) {
|
||||||
return casted_lhs;
|
return casted_lhs;
|
||||||
}
|
}
|
||||||
if (maybe_lhs_val) |lhs_val| {
|
if (maybe_lhs_val) |lhs_val| {
|
||||||
|
|
@ -14968,7 +15017,7 @@ fn analyzeArithmetic(
|
||||||
})
|
})
|
||||||
else
|
else
|
||||||
ov_bit;
|
ov_bit;
|
||||||
const zero_ov = try sema.addConstant(Type.u1, Value.zero);
|
const zero_ov = try sema.addConstant(Type.u1, try mod.intValue(Type.u1, 0));
|
||||||
const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov);
|
const no_ov = try block.addBinOp(.cmp_eq, any_ov_bit, zero_ov);
|
||||||
|
|
||||||
try sema.addSafetyCheck(block, no_ov, .integer_overflow);
|
try sema.addSafetyCheck(block, no_ov, .integer_overflow);
|
||||||
|
|
@ -15785,7 +15834,7 @@ fn zirBuiltinSrc(
|
||||||
const name = std.mem.span(fn_owner_decl.name);
|
const name = std.mem.span(fn_owner_decl.name);
|
||||||
const bytes = try anon_decl.arena().dupe(u8, name[0 .. name.len + 1]);
|
const bytes = try anon_decl.arena().dupe(u8, name[0 .. name.len + 1]);
|
||||||
const new_decl = try anon_decl.finish(
|
const new_decl = try anon_decl.finish(
|
||||||
try Type.array(anon_decl.arena(), bytes.len - 1, Value.zero, Type.u8, mod),
|
try Type.array(anon_decl.arena(), bytes.len - 1, try mod.intValue(Type.u8, 0), Type.u8, mod),
|
||||||
try Value.Tag.bytes.create(anon_decl.arena(), bytes),
|
try Value.Tag.bytes.create(anon_decl.arena(), bytes),
|
||||||
0, // default alignment
|
0, // default alignment
|
||||||
);
|
);
|
||||||
|
|
@ -15798,7 +15847,7 @@ fn zirBuiltinSrc(
|
||||||
// The compiler must not call realpath anywhere.
|
// The compiler must not call realpath anywhere.
|
||||||
const name = try fn_owner_decl.getFileScope().fullPathZ(anon_decl.arena());
|
const name = try fn_owner_decl.getFileScope().fullPathZ(anon_decl.arena());
|
||||||
const new_decl = try anon_decl.finish(
|
const new_decl = try anon_decl.finish(
|
||||||
try Type.array(anon_decl.arena(), name.len, Value.zero, Type.u8, mod),
|
try Type.array(anon_decl.arena(), name.len, try mod.intValue(Type.u8, 0), Type.u8, mod),
|
||||||
try Value.Tag.bytes.create(anon_decl.arena(), name[0 .. name.len + 1]),
|
try Value.Tag.bytes.create(anon_decl.arena(), name[0 .. name.len + 1]),
|
||||||
0, // default alignment
|
0, // default alignment
|
||||||
);
|
);
|
||||||
|
|
@ -16148,7 +16197,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
defer anon_decl.deinit();
|
defer anon_decl.deinit();
|
||||||
const bytes = try anon_decl.arena().dupeZ(u8, name);
|
const bytes = try anon_decl.arena().dupeZ(u8, name);
|
||||||
const new_decl = try anon_decl.finish(
|
const new_decl = try anon_decl.finish(
|
||||||
try Type.array(anon_decl.arena(), bytes.len, Value.zero, Type.u8, mod),
|
try Type.array(anon_decl.arena(), bytes.len, try mod.intValue(Type.u8, 0), Type.u8, mod),
|
||||||
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
||||||
0, // default alignment
|
0, // default alignment
|
||||||
);
|
);
|
||||||
|
|
@ -16256,7 +16305,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
defer anon_decl.deinit();
|
defer anon_decl.deinit();
|
||||||
const bytes = try anon_decl.arena().dupeZ(u8, name);
|
const bytes = try anon_decl.arena().dupeZ(u8, name);
|
||||||
const new_decl = try anon_decl.finish(
|
const new_decl = try anon_decl.finish(
|
||||||
try Type.array(anon_decl.arena(), bytes.len, Value.zero, Type.u8, mod),
|
try Type.array(anon_decl.arena(), bytes.len, try mod.intValue(Type.u8, 0), Type.u8, mod),
|
||||||
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
||||||
0, // default alignment
|
0, // default alignment
|
||||||
);
|
);
|
||||||
|
|
@ -16344,7 +16393,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
defer anon_decl.deinit();
|
defer anon_decl.deinit();
|
||||||
const bytes = try anon_decl.arena().dupeZ(u8, name);
|
const bytes = try anon_decl.arena().dupeZ(u8, name);
|
||||||
const new_decl = try anon_decl.finish(
|
const new_decl = try anon_decl.finish(
|
||||||
try Type.array(anon_decl.arena(), bytes.len, Value.zero, Type.u8, mod),
|
try Type.array(anon_decl.arena(), bytes.len, try mod.intValue(Type.u8, 0), Type.u8, mod),
|
||||||
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
||||||
0, // default alignment
|
0, // default alignment
|
||||||
);
|
);
|
||||||
|
|
@ -16454,7 +16503,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
else
|
else
|
||||||
try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});
|
try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});
|
||||||
const new_decl = try anon_decl.finish(
|
const new_decl = try anon_decl.finish(
|
||||||
try Type.array(anon_decl.arena(), bytes.len, Value.zero, Type.u8, mod),
|
try Type.array(anon_decl.arena(), bytes.len, try mod.intValue(Type.u8, 0), Type.u8, mod),
|
||||||
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
||||||
0, // default alignment
|
0, // default alignment
|
||||||
);
|
);
|
||||||
|
|
@ -16496,7 +16545,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
defer anon_decl.deinit();
|
defer anon_decl.deinit();
|
||||||
const bytes = try anon_decl.arena().dupeZ(u8, name);
|
const bytes = try anon_decl.arena().dupeZ(u8, name);
|
||||||
const new_decl = try anon_decl.finish(
|
const new_decl = try anon_decl.finish(
|
||||||
try Type.array(anon_decl.arena(), bytes.len, Value.zero, Type.u8, mod),
|
try Type.array(anon_decl.arena(), bytes.len, try mod.intValue(Type.u8, 0), Type.u8, mod),
|
||||||
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
||||||
0, // default alignment
|
0, // default alignment
|
||||||
);
|
);
|
||||||
|
|
@ -16692,7 +16741,7 @@ fn typeInfoNamespaceDecls(
|
||||||
defer anon_decl.deinit();
|
defer anon_decl.deinit();
|
||||||
const bytes = try anon_decl.arena().dupeZ(u8, mem.sliceTo(decl.name, 0));
|
const bytes = try anon_decl.arena().dupeZ(u8, mem.sliceTo(decl.name, 0));
|
||||||
const new_decl = try anon_decl.finish(
|
const new_decl = try anon_decl.finish(
|
||||||
try Type.array(anon_decl.arena(), bytes.len, Value.zero, Type.u8, mod),
|
try Type.array(anon_decl.arena(), bytes.len, try mod.intValue(Type.u8, 0), Type.u8, mod),
|
||||||
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
||||||
0, // default alignment
|
0, // default alignment
|
||||||
);
|
);
|
||||||
|
|
@ -17884,7 +17933,7 @@ fn zirStructInit(
|
||||||
}
|
}
|
||||||
found_fields[field_index] = item.data.field_type;
|
found_fields[field_index] = item.data.field_type;
|
||||||
field_inits[field_index] = try sema.resolveInst(item.data.init);
|
field_inits[field_index] = try sema.resolveInst(item.data.init);
|
||||||
if (!is_packed) if (resolved_ty.structFieldValueComptime(mod, field_index)) |default_value| {
|
if (!is_packed) if (try resolved_ty.structFieldValueComptime(mod, field_index)) |default_value| {
|
||||||
const init_val = (try sema.resolveMaybeUndefVal(field_inits[field_index])) orelse {
|
const init_val = (try sema.resolveMaybeUndefVal(field_inits[field_index])) orelse {
|
||||||
return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
|
return sema.failWithNeededComptime(block, field_src, "value stored in comptime field must be comptime-known");
|
||||||
};
|
};
|
||||||
|
|
@ -18544,8 +18593,8 @@ fn zirBoolToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||||
const operand = try sema.resolveInst(inst_data.operand);
|
const operand = try sema.resolveInst(inst_data.operand);
|
||||||
if (try sema.resolveMaybeUndefVal(operand)) |val| {
|
if (try sema.resolveMaybeUndefVal(operand)) |val| {
|
||||||
if (val.isUndef()) return sema.addConstUndef(Type.u1);
|
if (val.isUndef()) return sema.addConstUndef(Type.u1);
|
||||||
if (val.toBool(mod)) return sema.addConstant(Type.u1, Value.one);
|
if (val.toBool(mod)) return sema.addConstant(Type.u1, try mod.intValue(Type.u1, 1));
|
||||||
return sema.addConstant(Type.u1, Value.zero);
|
return sema.addConstant(Type.u1, try mod.intValue(Type.u1, 0));
|
||||||
}
|
}
|
||||||
return block.addUnOp(.bool_to_int, operand);
|
return block.addUnOp(.bool_to_int, operand);
|
||||||
}
|
}
|
||||||
|
|
@ -19761,7 +19810,7 @@ fn zirTypeName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
||||||
const bytes = try ty.nameAllocArena(anon_decl.arena(), mod);
|
const bytes = try ty.nameAllocArena(anon_decl.arena(), mod);
|
||||||
|
|
||||||
const new_decl = try anon_decl.finish(
|
const new_decl = try anon_decl.finish(
|
||||||
try Type.array(anon_decl.arena(), bytes.len, Value.zero, Type.u8, mod),
|
try Type.array(anon_decl.arena(), bytes.len, try mod.intValue(Type.u8, 0), Type.u8, mod),
|
||||||
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
||||||
0, // default alignment
|
0, // default alignment
|
||||||
);
|
);
|
||||||
|
|
@ -19804,17 +19853,17 @@ fn zirFloatToInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
|
||||||
try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);
|
try sema.requireRuntimeBlock(block, inst_data.src(), operand_src);
|
||||||
if (dest_ty.intInfo(mod).bits == 0) {
|
if (dest_ty.intInfo(mod).bits == 0) {
|
||||||
if (block.wantSafety()) {
|
if (block.wantSafety()) {
|
||||||
const ok = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, try sema.addConstant(operand_ty, Value.zero));
|
const ok = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_eq_optimized else .cmp_eq, operand, try sema.addConstant(operand_ty, try mod.intValue(operand_ty, 0)));
|
||||||
try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
|
try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
|
||||||
}
|
}
|
||||||
return sema.addConstant(dest_ty, Value.zero);
|
return sema.addConstant(dest_ty, try mod.intValue(dest_ty, 0));
|
||||||
}
|
}
|
||||||
const result = try block.addTyOp(if (block.float_mode == .Optimized) .float_to_int_optimized else .float_to_int, dest_ty, operand);
|
const result = try block.addTyOp(if (block.float_mode == .Optimized) .float_to_int_optimized else .float_to_int, dest_ty, operand);
|
||||||
if (block.wantSafety()) {
|
if (block.wantSafety()) {
|
||||||
const back = try block.addTyOp(.int_to_float, operand_ty, result);
|
const back = try block.addTyOp(.int_to_float, operand_ty, result);
|
||||||
const diff = try block.addBinOp(.sub, operand, back);
|
const diff = try block.addBinOp(.sub, operand, back);
|
||||||
const ok_pos = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_lt_optimized else .cmp_lt, diff, try sema.addConstant(operand_ty, Value.one));
|
const ok_pos = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_lt_optimized else .cmp_lt, diff, try sema.addConstant(operand_ty, try mod.intValue(operand_ty, 1)));
|
||||||
const ok_neg = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_gt_optimized else .cmp_gt, diff, try sema.addConstant(operand_ty, Value.negative_one));
|
const ok_neg = try block.addBinOp(if (block.float_mode == .Optimized) .cmp_gt_optimized else .cmp_gt, diff, try sema.addConstant(operand_ty, try mod.intValue(operand_ty, -1)));
|
||||||
const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);
|
const ok = try block.addBinOp(.bool_and, ok_pos, ok_neg);
|
||||||
try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
|
try sema.addSafetyCheck(block, ok, .integer_part_out_of_bounds);
|
||||||
}
|
}
|
||||||
|
|
@ -21398,7 +21447,7 @@ fn analyzeShuffle(
|
||||||
expand_mask_values[i] = try mod.intValue(Type.comptime_int, i);
|
expand_mask_values[i] = try mod.intValue(Type.comptime_int, i);
|
||||||
}
|
}
|
||||||
while (i < max_len) : (i += 1) {
|
while (i < max_len) : (i += 1) {
|
||||||
expand_mask_values[i] = Value.negative_one;
|
expand_mask_values[i] = try mod.intValue(Type.comptime_int, -1);
|
||||||
}
|
}
|
||||||
const expand_mask = try Value.Tag.aggregate.create(sema.arena, expand_mask_values);
|
const expand_mask = try Value.Tag.aggregate.create(sema.arena, expand_mask_values);
|
||||||
|
|
||||||
|
|
@ -24504,7 +24553,7 @@ fn finishFieldCallBind(
|
||||||
|
|
||||||
const container_ty = ptr_ty.childType(mod);
|
const container_ty = ptr_ty.childType(mod);
|
||||||
if (container_ty.zigTypeTag(mod) == .Struct) {
|
if (container_ty.zigTypeTag(mod) == .Struct) {
|
||||||
if (container_ty.structFieldValueComptime(mod, field_index)) |default_val| {
|
if (try container_ty.structFieldValueComptime(mod, field_index)) |default_val| {
|
||||||
return .{ .direct = try sema.addConstant(field_ty, default_val) };
|
return .{ .direct = try sema.addConstant(field_ty, default_val) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -24815,7 +24864,7 @@ fn tupleFieldValByIndex(
|
||||||
const mod = sema.mod;
|
const mod = sema.mod;
|
||||||
const field_ty = tuple_ty.structFieldType(field_index);
|
const field_ty = tuple_ty.structFieldType(field_index);
|
||||||
|
|
||||||
if (tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {
|
if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {
|
||||||
return sema.addConstant(field_ty, default_value);
|
return sema.addConstant(field_ty, default_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -24828,7 +24877,7 @@ fn tupleFieldValByIndex(
|
||||||
return sema.addConstant(field_ty, field_values[field_index]);
|
return sema.addConstant(field_ty, field_values[field_index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {
|
if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {
|
||||||
return sema.addConstant(field_ty, default_val);
|
return sema.addConstant(field_ty, default_val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25205,7 +25254,7 @@ fn tupleFieldPtr(
|
||||||
.@"addrspace" = tuple_ptr_ty.ptrAddressSpace(mod),
|
.@"addrspace" = tuple_ptr_ty.ptrAddressSpace(mod),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {
|
if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_val| {
|
||||||
const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{
|
const val = try Value.Tag.comptime_field_ptr.create(sema.arena, .{
|
||||||
.field_ty = field_ty,
|
.field_ty = field_ty,
|
||||||
.field_val = default_val,
|
.field_val = default_val,
|
||||||
|
|
@ -25256,13 +25305,13 @@ fn tupleField(
|
||||||
|
|
||||||
const field_ty = tuple_ty.structFieldType(field_index);
|
const field_ty = tuple_ty.structFieldType(field_index);
|
||||||
|
|
||||||
if (tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {
|
if (try tuple_ty.structFieldValueComptime(mod, field_index)) |default_value| {
|
||||||
return sema.addConstant(field_ty, default_value); // comptime field
|
return sema.addConstant(field_ty, default_value); // comptime field
|
||||||
}
|
}
|
||||||
|
|
||||||
if (try sema.resolveMaybeUndefVal(tuple)) |tuple_val| {
|
if (try sema.resolveMaybeUndefVal(tuple)) |tuple_val| {
|
||||||
if (tuple_val.isUndef()) return sema.addConstUndef(field_ty);
|
if (tuple_val.isUndef()) return sema.addConstUndef(field_ty);
|
||||||
return sema.addConstant(field_ty, tuple_val.fieldValue(tuple_ty, mod, field_index));
|
return sema.addConstant(field_ty, try tuple_val.fieldValue(tuple_ty, mod, field_index));
|
||||||
}
|
}
|
||||||
|
|
||||||
try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
|
try sema.validateRuntimeElemAccess(block, field_index_src, field_ty, tuple_ty, tuple_src);
|
||||||
|
|
@ -25812,7 +25861,7 @@ fn coerceExtra(
|
||||||
if (inst_info.size == .Slice) {
|
if (inst_info.size == .Slice) {
|
||||||
assert(dest_info.sentinel == null);
|
assert(dest_info.sentinel == null);
|
||||||
if (inst_info.sentinel == null or
|
if (inst_info.sentinel == null or
|
||||||
!inst_info.sentinel.?.eql(Value.zero, dest_info.pointee_type, sema.mod))
|
!inst_info.sentinel.?.eql(try mod.intValue(dest_info.pointee_type, 0), dest_info.pointee_type, sema.mod))
|
||||||
break :p;
|
break :p;
|
||||||
|
|
||||||
const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty);
|
const slice_ptr = try sema.analyzeSlicePtr(block, inst_src, inst, inst_ty);
|
||||||
|
|
@ -25879,7 +25928,7 @@ fn coerceExtra(
|
||||||
try mod.intValue(Type.usize, dest_info.@"align")
|
try mod.intValue(Type.usize, dest_info.@"align")
|
||||||
else
|
else
|
||||||
try dest_info.pointee_type.lazyAbiAlignment(mod, sema.arena),
|
try dest_info.pointee_type.lazyAbiAlignment(mod, sema.arena),
|
||||||
.len = Value.zero,
|
.len = try mod.intValue(Type.usize, 0),
|
||||||
});
|
});
|
||||||
return sema.addConstant(dest_ty, slice_val);
|
return sema.addConstant(dest_ty, slice_val);
|
||||||
}
|
}
|
||||||
|
|
@ -28234,7 +28283,7 @@ fn beginComptimePtrLoad(
|
||||||
const field_ty = field_ptr.container_ty.structFieldType(field_index);
|
const field_ty = field_ptr.container_ty.structFieldType(field_index);
|
||||||
deref.pointee = TypedValue{
|
deref.pointee = TypedValue{
|
||||||
.ty = field_ty,
|
.ty = field_ty,
|
||||||
.val = tv.val.fieldValue(tv.ty, mod, field_index),
|
.val = try tv.val.fieldValue(tv.ty, mod, field_index),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
break :blk deref;
|
break :blk deref;
|
||||||
|
|
@ -32532,9 +32581,9 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
|
||||||
break :blk try val.copy(decl_arena_allocator);
|
break :blk try val.copy(decl_arena_allocator);
|
||||||
} else blk: {
|
} else blk: {
|
||||||
const val = if (last_tag_val) |val|
|
const val = if (last_tag_val) |val|
|
||||||
try sema.intAdd(val, Value.one, int_tag_ty)
|
try sema.intAdd(val, try mod.intValue(int_tag_ty, 1), int_tag_ty)
|
||||||
else
|
else
|
||||||
Value.zero;
|
try mod.intValue(int_tag_ty, 0);
|
||||||
last_tag_val = val;
|
last_tag_val = val;
|
||||||
|
|
||||||
break :blk try val.copy(decl_arena_allocator);
|
break :blk try val.copy(decl_arena_allocator);
|
||||||
|
|
@ -32903,7 +32952,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||||
if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
|
if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
|
||||||
.int_type => |int_type| {
|
.int_type => |int_type| {
|
||||||
if (int_type.bits == 0) {
|
if (int_type.bits == 0) {
|
||||||
return Value.zero;
|
return try mod.intValue(ty, 0);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -33049,7 +33098,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||||
}
|
}
|
||||||
if (enum_obj.fields.count() == 1) {
|
if (enum_obj.fields.count() == 1) {
|
||||||
if (enum_obj.values.count() == 0) {
|
if (enum_obj.values.count() == 0) {
|
||||||
return Value.zero; // auto-numbered
|
return try mod.intValue(ty, 0); // auto-numbered
|
||||||
} else {
|
} else {
|
||||||
return enum_obj.values.keys()[0];
|
return enum_obj.values.keys()[0];
|
||||||
}
|
}
|
||||||
|
|
@ -33066,7 +33115,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||||
switch (enum_obj.fields.count()) {
|
switch (enum_obj.fields.count()) {
|
||||||
0 => return Value.@"unreachable",
|
0 => return Value.@"unreachable",
|
||||||
1 => if (enum_obj.values.count() == 0) {
|
1 => if (enum_obj.values.count() == 0) {
|
||||||
return Value.zero; // auto-numbered
|
return try mod.intValue(ty, 0); // auto-numbered
|
||||||
} else {
|
} else {
|
||||||
return enum_obj.values.keys()[0];
|
return enum_obj.values.keys()[0];
|
||||||
},
|
},
|
||||||
|
|
@ -33078,14 +33127,14 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||||
const enum_simple = resolved_ty.castTag(.enum_simple).?.data;
|
const enum_simple = resolved_ty.castTag(.enum_simple).?.data;
|
||||||
switch (enum_simple.fields.count()) {
|
switch (enum_simple.fields.count()) {
|
||||||
0 => return Value.@"unreachable",
|
0 => return Value.@"unreachable",
|
||||||
1 => return Value.zero,
|
1 => return try mod.intValue(ty, 0),
|
||||||
else => return null,
|
else => return null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.enum_nonexhaustive => {
|
.enum_nonexhaustive => {
|
||||||
const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
|
const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
|
||||||
if (tag_ty.zigTypeTag(mod) != .ComptimeInt and !(try sema.typeHasRuntimeBits(tag_ty))) {
|
if (tag_ty.zigTypeTag(mod) != .ComptimeInt and !(try sema.typeHasRuntimeBits(tag_ty))) {
|
||||||
return Value.zero;
|
return try mod.intValue(ty, 0);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,10 @@ pub fn format(
|
||||||
) !void {
|
) !void {
|
||||||
_ = options;
|
_ = options;
|
||||||
comptime std.debug.assert(fmt.len == 0);
|
comptime std.debug.assert(fmt.len == 0);
|
||||||
return ctx.tv.print(writer, 3, ctx.mod);
|
return ctx.tv.print(writer, 3, ctx.mod) catch |err| switch (err) {
|
||||||
|
error.OutOfMemory => @panic("OOM"), // We're not allowed to return this from a format function
|
||||||
|
else => |e| return e,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prints the Value according to the Type, not according to the Value Tag.
|
/// Prints the Value according to the Type, not according to the Value Tag.
|
||||||
|
|
@ -70,7 +73,7 @@ pub fn print(
|
||||||
writer: anytype,
|
writer: anytype,
|
||||||
level: u8,
|
level: u8,
|
||||||
mod: *Module,
|
mod: *Module,
|
||||||
) @TypeOf(writer).Error!void {
|
) (@TypeOf(writer).Error || Allocator.Error)!void {
|
||||||
var val = tv.val;
|
var val = tv.val;
|
||||||
var ty = tv.ty;
|
var ty = tv.ty;
|
||||||
if (val.isVariable(mod))
|
if (val.isVariable(mod))
|
||||||
|
|
@ -95,7 +98,7 @@ pub fn print(
|
||||||
}
|
}
|
||||||
try print(.{
|
try print(.{
|
||||||
.ty = ty.structFieldType(i),
|
.ty = ty.structFieldType(i),
|
||||||
.val = val.fieldValue(ty, mod, i),
|
.val = try val.fieldValue(ty, mod, i),
|
||||||
}, writer, level - 1, mod);
|
}, writer, level - 1, mod);
|
||||||
}
|
}
|
||||||
if (ty.structFieldCount() > max_aggregate_items) {
|
if (ty.structFieldCount() > max_aggregate_items) {
|
||||||
|
|
@ -112,7 +115,7 @@ pub fn print(
|
||||||
|
|
||||||
var i: u32 = 0;
|
var i: u32 = 0;
|
||||||
while (i < max_len) : (i += 1) {
|
while (i < max_len) : (i += 1) {
|
||||||
const elem = val.fieldValue(ty, mod, i);
|
const elem = try val.fieldValue(ty, mod, i);
|
||||||
if (elem.isUndef()) break :str;
|
if (elem.isUndef()) break :str;
|
||||||
buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;
|
buf[i] = std.math.cast(u8, elem.toUnsignedInt(mod)) orelse break :str;
|
||||||
}
|
}
|
||||||
|
|
@ -129,7 +132,7 @@ pub fn print(
|
||||||
if (i != 0) try writer.writeAll(", ");
|
if (i != 0) try writer.writeAll(", ");
|
||||||
try print(.{
|
try print(.{
|
||||||
.ty = elem_ty,
|
.ty = elem_ty,
|
||||||
.val = val.fieldValue(ty, mod, i),
|
.val = try val.fieldValue(ty, mod, i),
|
||||||
}, writer, level - 1, mod);
|
}, writer, level - 1, mod);
|
||||||
}
|
}
|
||||||
if (len > max_aggregate_items) {
|
if (len > max_aggregate_items) {
|
||||||
|
|
|
||||||
|
|
@ -4311,7 +4311,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
|
|
||||||
// Due to incremental compilation, how function calls are generated depends
|
// Due to incremental compilation, how function calls are generated depends
|
||||||
// on linking.
|
// on linking.
|
||||||
if (self.air.value(callee, mod)) |func_value| {
|
if (try self.air.value(callee, mod)) |func_value| {
|
||||||
if (func_value.castTag(.function)) |func_payload| {
|
if (func_value.castTag(.function)) |func_payload| {
|
||||||
const func = func_payload.data;
|
const func = func_payload.data;
|
||||||
|
|
||||||
|
|
@ -6154,7 +6154,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
|
||||||
|
|
||||||
const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{
|
const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{
|
||||||
.ty = inst_ty,
|
.ty = inst_ty,
|
||||||
.val = self.air.value(inst, mod).?,
|
.val = (try self.air.value(inst, mod)).?,
|
||||||
});
|
});
|
||||||
|
|
||||||
switch (self.air.instructions.items(.tag)[inst_index]) {
|
switch (self.air.instructions.items(.tag)[inst_index]) {
|
||||||
|
|
|
||||||
|
|
@ -4291,7 +4291,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
|
|
||||||
// Due to incremental compilation, how function calls are generated depends
|
// Due to incremental compilation, how function calls are generated depends
|
||||||
// on linking.
|
// on linking.
|
||||||
if (self.air.value(callee, mod)) |func_value| {
|
if (try self.air.value(callee, mod)) |func_value| {
|
||||||
if (func_value.castTag(.function)) |func_payload| {
|
if (func_value.castTag(.function)) |func_payload| {
|
||||||
const func = func_payload.data;
|
const func = func_payload.data;
|
||||||
|
|
||||||
|
|
@ -6101,7 +6101,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
|
||||||
|
|
||||||
const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{
|
const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{
|
||||||
.ty = inst_ty,
|
.ty = inst_ty,
|
||||||
.val = self.air.value(inst, mod).?,
|
.val = (try self.air.value(inst, mod)).?,
|
||||||
});
|
});
|
||||||
|
|
||||||
switch (self.air.instructions.items(.tag)[inst_index]) {
|
switch (self.air.instructions.items(.tag)[inst_index]) {
|
||||||
|
|
|
||||||
|
|
@ -1743,7 +1743,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.air.value(callee, mod)) |func_value| {
|
if (try self.air.value(callee, mod)) |func_value| {
|
||||||
if (func_value.castTag(.function)) |func_payload| {
|
if (func_value.castTag(.function)) |func_payload| {
|
||||||
const func = func_payload.data;
|
const func = func_payload.data;
|
||||||
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
||||||
|
|
@ -2551,7 +2551,7 @@ fn resolveInst(self: *Self, inst: Air.Inst.Ref) InnerError!MCValue {
|
||||||
|
|
||||||
const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{
|
const inst_index = Air.refToIndex(inst) orelse return self.genTypedValue(.{
|
||||||
.ty = inst_ty,
|
.ty = inst_ty,
|
||||||
.val = self.air.value(inst, mod).?,
|
.val = (try self.air.value(inst, mod)).?,
|
||||||
});
|
});
|
||||||
|
|
||||||
switch (self.air.instructions.items(.tag)[inst_index]) {
|
switch (self.air.instructions.items(.tag)[inst_index]) {
|
||||||
|
|
|
||||||
|
|
@ -1343,7 +1343,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
|
|
||||||
// Due to incremental compilation, how function calls are generated depends
|
// Due to incremental compilation, how function calls are generated depends
|
||||||
// on linking.
|
// on linking.
|
||||||
if (self.air.value(callee, mod)) |func_value| {
|
if (try self.air.value(callee, mod)) |func_value| {
|
||||||
if (self.bin_file.tag == link.File.Elf.base_tag) {
|
if (self.bin_file.tag == link.File.Elf.base_tag) {
|
||||||
if (func_value.castTag(.function)) |func_payload| {
|
if (func_value.castTag(.function)) |func_payload| {
|
||||||
const func = func_payload.data;
|
const func = func_payload.data;
|
||||||
|
|
@ -4575,7 +4575,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
|
||||||
|
|
||||||
return self.genTypedValue(.{
|
return self.genTypedValue(.{
|
||||||
.ty = ty,
|
.ty = ty,
|
||||||
.val = self.air.value(ref, mod).?,
|
.val = (try self.air.value(ref, mod)).?,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -789,7 +789,7 @@ fn resolveInst(func: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue {
|
||||||
assert(!gop.found_existing);
|
assert(!gop.found_existing);
|
||||||
|
|
||||||
const mod = func.bin_file.base.options.module.?;
|
const mod = func.bin_file.base.options.module.?;
|
||||||
const val = func.air.value(ref, mod).?;
|
const val = (try func.air.value(ref, mod)).?;
|
||||||
const ty = func.typeOf(ref);
|
const ty = func.typeOf(ref);
|
||||||
if (!ty.hasRuntimeBitsIgnoreComptime(mod) and !ty.isInt(mod) and !ty.isError(mod)) {
|
if (!ty.hasRuntimeBitsIgnoreComptime(mod) and !ty.isInt(mod) and !ty.isError(mod)) {
|
||||||
gop.value_ptr.* = WValue{ .none = {} };
|
gop.value_ptr.* = WValue{ .none = {} };
|
||||||
|
|
@ -2195,7 +2195,7 @@ fn airCall(func: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModif
|
||||||
const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type, mod);
|
const first_param_sret = firstParamSRet(fn_info.cc, fn_info.return_type, mod);
|
||||||
|
|
||||||
const callee: ?Decl.Index = blk: {
|
const callee: ?Decl.Index = blk: {
|
||||||
const func_val = func.air.value(pl_op.operand, mod) orelse break :blk null;
|
const func_val = (try func.air.value(pl_op.operand, mod)) orelse break :blk null;
|
||||||
|
|
||||||
if (func_val.castTag(.function)) |function| {
|
if (func_val.castTag(.function)) |function| {
|
||||||
_ = try func.bin_file.getOrCreateAtomForDecl(function.data.owner_decl);
|
_ = try func.bin_file.getOrCreateAtomForDecl(function.data.owner_decl);
|
||||||
|
|
@ -3138,7 +3138,7 @@ fn lowerConstant(func: *CodeGen, arg_val: Value, ty: Type) InnerError!WValue {
|
||||||
if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
|
if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||||
// We use the error type directly as the type.
|
// We use the error type directly as the type.
|
||||||
const is_pl = val.errorUnionIsPayload();
|
const is_pl = val.errorUnionIsPayload();
|
||||||
const err_val = if (!is_pl) val else Value.zero;
|
const err_val = if (!is_pl) val else try mod.intValue(error_type, 0);
|
||||||
return func.lowerConstant(err_val, error_type);
|
return func.lowerConstant(err_val, error_type);
|
||||||
}
|
}
|
||||||
return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{});
|
return func.fail("Wasm TODO: lowerConstant error union with non-zero-bit payload type", .{});
|
||||||
|
|
@ -3792,7 +3792,7 @@ fn airSwitchBr(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||||
errdefer func.gpa.free(values);
|
errdefer func.gpa.free(values);
|
||||||
|
|
||||||
for (items, 0..) |ref, i| {
|
for (items, 0..) |ref, i| {
|
||||||
const item_val = func.air.value(ref, mod).?;
|
const item_val = (try func.air.value(ref, mod)).?;
|
||||||
const int_val = func.valueAsI32(item_val, target_ty);
|
const int_val = func.valueAsI32(item_val, target_ty);
|
||||||
if (lowest_maybe == null or int_val < lowest_maybe.?) {
|
if (lowest_maybe == null or int_val < lowest_maybe.?) {
|
||||||
lowest_maybe = int_val;
|
lowest_maybe = int_val;
|
||||||
|
|
@ -5048,7 +5048,7 @@ fn airAggregateInit(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||||
const result = try func.allocStack(result_ty);
|
const result = try func.allocStack(result_ty);
|
||||||
const offset = try func.buildPointerOffset(result, 0, .new); // pointer to offset
|
const offset = try func.buildPointerOffset(result, 0, .new); // pointer to offset
|
||||||
for (elements, 0..) |elem, elem_index| {
|
for (elements, 0..) |elem, elem_index| {
|
||||||
if (result_ty.structFieldValueComptime(mod, elem_index) != null) continue;
|
if ((try result_ty.structFieldValueComptime(mod, elem_index)) != null) continue;
|
||||||
|
|
||||||
const elem_ty = result_ty.structFieldType(elem_index);
|
const elem_ty = result_ty.structFieldType(elem_index);
|
||||||
const elem_size = @intCast(u32, elem_ty.abiSize(mod));
|
const elem_size = @intCast(u32, elem_ty.abiSize(mod));
|
||||||
|
|
|
||||||
|
|
@ -2768,7 +2768,7 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
|
|
||||||
const full_ty = try mod.vectorType(.{
|
const full_ty = try mod.vectorType(.{
|
||||||
.len = @intCast(u32, @divExact(@as(u64, if (src_abi_size > 16) 256 else 128), src_info.bits)),
|
.len = @intCast(u32, @divExact(@as(u64, if (src_abi_size > 16) 256 else 128), src_info.bits)),
|
||||||
.child = src_ty.childType(mod).ip_index,
|
.child = elem_ty.ip_index,
|
||||||
});
|
});
|
||||||
const full_abi_size = @intCast(u32, full_ty.abiSize(mod));
|
const full_abi_size = @intCast(u32, full_ty.abiSize(mod));
|
||||||
|
|
||||||
|
|
@ -8107,7 +8107,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
|
|
||||||
// Due to incremental compilation, how function calls are generated depends
|
// Due to incremental compilation, how function calls are generated depends
|
||||||
// on linking.
|
// on linking.
|
||||||
if (self.air.value(callee, mod)) |func_value| {
|
if (try self.air.value(callee, mod)) |func_value| {
|
||||||
if (if (func_value.castTag(.function)) |func_payload|
|
if (if (func_value.castTag(.function)) |func_payload|
|
||||||
func_payload.data.owner_decl
|
func_payload.data.owner_decl
|
||||||
else if (func_value.castTag(.decl_ref)) |decl_ref_payload|
|
else if (func_value.castTag(.decl_ref)) |decl_ref_payload|
|
||||||
|
|
@ -11265,7 +11265,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
.{ .immediate = result_ty.abiSize(mod) },
|
.{ .immediate = result_ty.abiSize(mod) },
|
||||||
);
|
);
|
||||||
for (elements, 0..) |elem, elem_i| {
|
for (elements, 0..) |elem, elem_i| {
|
||||||
if (result_ty.structFieldValueComptime(mod, elem_i) != null) continue;
|
if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue;
|
||||||
|
|
||||||
const elem_ty = result_ty.structFieldType(elem_i);
|
const elem_ty = result_ty.structFieldType(elem_i);
|
||||||
const elem_bit_size = @intCast(u32, elem_ty.bitSize(mod));
|
const elem_bit_size = @intCast(u32, elem_ty.bitSize(mod));
|
||||||
|
|
@ -11337,7 +11337,7 @@ fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else for (elements, 0..) |elem, elem_i| {
|
} else for (elements, 0..) |elem, elem_i| {
|
||||||
if (result_ty.structFieldValueComptime(mod, elem_i) != null) continue;
|
if ((try result_ty.structFieldValueComptime(mod, elem_i)) != null) continue;
|
||||||
|
|
||||||
const elem_ty = result_ty.structFieldType(elem_i);
|
const elem_ty = result_ty.structFieldType(elem_i);
|
||||||
const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, mod));
|
const elem_off = @intCast(i32, result_ty.structFieldOffset(elem_i, mod));
|
||||||
|
|
@ -11601,7 +11601,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
|
||||||
const gop = try self.const_tracking.getOrPut(self.gpa, inst);
|
const gop = try self.const_tracking.getOrPut(self.gpa, inst);
|
||||||
if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{
|
if (!gop.found_existing) gop.value_ptr.* = InstTracking.init(try self.genTypedValue(.{
|
||||||
.ty = ty,
|
.ty = ty,
|
||||||
.val = self.air.value(ref, mod).?,
|
.val = (try self.air.value(ref, mod)).?,
|
||||||
}));
|
}));
|
||||||
break :tracking gop.value_ptr;
|
break :tracking gop.value_ptr;
|
||||||
},
|
},
|
||||||
|
|
@ -11614,7 +11614,7 @@ fn resolveInst(self: *Self, ref: Air.Inst.Ref) InnerError!MCValue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.genTypedValue(.{ .ty = ty, .val = self.air.value(ref, mod).? });
|
return self.genTypedValue(.{ .ty = ty, .val = (try self.air.value(ref, mod)).? });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking {
|
fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) *InstTracking {
|
||||||
|
|
|
||||||
|
|
@ -675,7 +675,7 @@ pub fn generateSymbol(
|
||||||
const is_payload = typed_value.val.errorUnionIsPayload();
|
const is_payload = typed_value.val.errorUnionIsPayload();
|
||||||
|
|
||||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||||
const err_val = if (is_payload) Value.zero else typed_value.val;
|
const err_val = if (is_payload) try mod.intValue(error_ty, 0) else typed_value.val;
|
||||||
return generateSymbol(bin_file, src_loc, .{
|
return generateSymbol(bin_file, src_loc, .{
|
||||||
.ty = error_ty,
|
.ty = error_ty,
|
||||||
.val = err_val,
|
.val = err_val,
|
||||||
|
|
@ -690,7 +690,7 @@ pub fn generateSymbol(
|
||||||
if (error_align > payload_align) {
|
if (error_align > payload_align) {
|
||||||
switch (try generateSymbol(bin_file, src_loc, .{
|
switch (try generateSymbol(bin_file, src_loc, .{
|
||||||
.ty = error_ty,
|
.ty = error_ty,
|
||||||
.val = if (is_payload) Value.zero else typed_value.val,
|
.val = if (is_payload) try mod.intValue(error_ty, 0) else typed_value.val,
|
||||||
}, code, debug_output, reloc_info)) {
|
}, code, debug_output, reloc_info)) {
|
||||||
.ok => {},
|
.ok => {},
|
||||||
.fail => |em| return Result{ .fail = em },
|
.fail => |em| return Result{ .fail = em },
|
||||||
|
|
@ -722,7 +722,7 @@ pub fn generateSymbol(
|
||||||
const begin = code.items.len;
|
const begin = code.items.len;
|
||||||
switch (try generateSymbol(bin_file, src_loc, .{
|
switch (try generateSymbol(bin_file, src_loc, .{
|
||||||
.ty = error_ty,
|
.ty = error_ty,
|
||||||
.val = if (is_payload) Value.zero else typed_value.val,
|
.val = if (is_payload) try mod.intValue(error_ty, 0) else typed_value.val,
|
||||||
}, code, debug_output, reloc_info)) {
|
}, code, debug_output, reloc_info)) {
|
||||||
.ok => {},
|
.ok => {},
|
||||||
.fail => |em| return Result{ .fail = em },
|
.fail => |em| return Result{ .fail = em },
|
||||||
|
|
@ -1280,7 +1280,7 @@ pub fn genTypedValue(
|
||||||
|
|
||||||
if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
|
if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||||
// We use the error type directly as the type.
|
// We use the error type directly as the type.
|
||||||
const err_val = if (!is_pl) typed_value.val else Value.zero;
|
const err_val = if (!is_pl) typed_value.val else try mod.intValue(error_type, 0);
|
||||||
return genTypedValue(bin_file, src_loc, .{
|
return genTypedValue(bin_file, src_loc, .{
|
||||||
.ty = error_type,
|
.ty = error_type,
|
||||||
.val = err_val,
|
.val = err_val,
|
||||||
|
|
|
||||||
|
|
@ -287,7 +287,7 @@ pub const Function = struct {
|
||||||
if (gop.found_existing) return gop.value_ptr.*;
|
if (gop.found_existing) return gop.value_ptr.*;
|
||||||
|
|
||||||
const mod = f.object.dg.module;
|
const mod = f.object.dg.module;
|
||||||
const val = f.air.value(ref, mod).?;
|
const val = (try f.air.value(ref, mod)).?;
|
||||||
const ty = f.typeOf(ref);
|
const ty = f.typeOf(ref);
|
||||||
|
|
||||||
const result: CValue = if (lowersToArray(ty, mod)) result: {
|
const result: CValue = if (lowersToArray(ty, mod)) result: {
|
||||||
|
|
@ -356,7 +356,7 @@ pub const Function = struct {
|
||||||
.constant => |inst| {
|
.constant => |inst| {
|
||||||
const mod = f.object.dg.module;
|
const mod = f.object.dg.module;
|
||||||
const ty = f.typeOf(inst);
|
const ty = f.typeOf(inst);
|
||||||
const val = f.air.value(inst, mod).?;
|
const val = (try f.air.value(inst, mod)).?;
|
||||||
return f.object.dg.renderValue(w, ty, val, location);
|
return f.object.dg.renderValue(w, ty, val, location);
|
||||||
},
|
},
|
||||||
.undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location),
|
.undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location),
|
||||||
|
|
@ -369,7 +369,7 @@ pub const Function = struct {
|
||||||
.constant => |inst| {
|
.constant => |inst| {
|
||||||
const mod = f.object.dg.module;
|
const mod = f.object.dg.module;
|
||||||
const ty = f.typeOf(inst);
|
const ty = f.typeOf(inst);
|
||||||
const val = f.air.value(inst, mod).?;
|
const val = (try f.air.value(inst, mod)).?;
|
||||||
try w.writeAll("(*");
|
try w.writeAll("(*");
|
||||||
try f.object.dg.renderValue(w, ty, val, .Other);
|
try f.object.dg.renderValue(w, ty, val, .Other);
|
||||||
return w.writeByte(')');
|
return w.writeByte(')');
|
||||||
|
|
@ -383,7 +383,7 @@ pub const Function = struct {
|
||||||
.constant => |inst| {
|
.constant => |inst| {
|
||||||
const mod = f.object.dg.module;
|
const mod = f.object.dg.module;
|
||||||
const ty = f.typeOf(inst);
|
const ty = f.typeOf(inst);
|
||||||
const val = f.air.value(inst, mod).?;
|
const val = (try f.air.value(inst, mod)).?;
|
||||||
try f.object.dg.renderValue(w, ty, val, .Other);
|
try f.object.dg.renderValue(w, ty, val, .Other);
|
||||||
try w.writeByte('.');
|
try w.writeByte('.');
|
||||||
return f.writeCValue(w, member, .Other);
|
return f.writeCValue(w, member, .Other);
|
||||||
|
|
@ -397,7 +397,7 @@ pub const Function = struct {
|
||||||
.constant => |inst| {
|
.constant => |inst| {
|
||||||
const mod = f.object.dg.module;
|
const mod = f.object.dg.module;
|
||||||
const ty = f.typeOf(inst);
|
const ty = f.typeOf(inst);
|
||||||
const val = f.air.value(inst, mod).?;
|
const val = (try f.air.value(inst, mod)).?;
|
||||||
try w.writeByte('(');
|
try w.writeByte('(');
|
||||||
try f.object.dg.renderValue(w, ty, val, .Other);
|
try f.object.dg.renderValue(w, ty, val, .Other);
|
||||||
try w.writeAll(")->");
|
try w.writeAll(")->");
|
||||||
|
|
@ -690,7 +690,7 @@ pub const DeclGen = struct {
|
||||||
location,
|
location,
|
||||||
);
|
);
|
||||||
try writer.print(") + {})", .{
|
try writer.print(") + {})", .{
|
||||||
try dg.fmtIntLiteral(Type.usize, Value.one, .Other),
|
try dg.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1), .Other),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -1253,7 +1253,7 @@ pub const DeclGen = struct {
|
||||||
.ErrorUnion => {
|
.ErrorUnion => {
|
||||||
const payload_ty = ty.errorUnionPayload();
|
const payload_ty = ty.errorUnionPayload();
|
||||||
const error_ty = ty.errorUnionSet();
|
const error_ty = ty.errorUnionSet();
|
||||||
const error_val = if (val.errorUnionIsPayload()) Value.zero else val;
|
const error_val = if (val.errorUnionIsPayload()) try mod.intValue(Type.anyerror, 0) else val;
|
||||||
|
|
||||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||||
return dg.renderValue(writer, error_ty, error_val, location);
|
return dg.renderValue(writer, error_ty, error_val, location);
|
||||||
|
|
@ -3611,7 +3611,7 @@ fn airStore(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
|
||||||
const ptr_val = try f.resolveInst(bin_op.lhs);
|
const ptr_val = try f.resolveInst(bin_op.lhs);
|
||||||
const src_ty = f.typeOf(bin_op.rhs);
|
const src_ty = f.typeOf(bin_op.rhs);
|
||||||
|
|
||||||
const val_is_undef = if (f.air.value(bin_op.rhs, mod)) |v| v.isUndefDeep() else false;
|
const val_is_undef = if (try f.air.value(bin_op.rhs, mod)) |v| v.isUndefDeep() else false;
|
||||||
|
|
||||||
if (val_is_undef) {
|
if (val_is_undef) {
|
||||||
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
|
try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
|
||||||
|
|
@ -4183,7 +4183,7 @@ fn airCall(
|
||||||
callee: {
|
callee: {
|
||||||
known: {
|
known: {
|
||||||
const fn_decl = fn_decl: {
|
const fn_decl = fn_decl: {
|
||||||
const callee_val = f.air.value(pl_op.operand, mod) orelse break :known;
|
const callee_val = (try f.air.value(pl_op.operand, mod)) orelse break :known;
|
||||||
break :fn_decl switch (callee_val.tag()) {
|
break :fn_decl switch (callee_val.tag()) {
|
||||||
.extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl,
|
.extern_fn => callee_val.castTag(.extern_fn).?.data.owner_decl,
|
||||||
.function => callee_val.castTag(.function).?.data.owner_decl,
|
.function => callee_val.castTag(.function).?.data.owner_decl,
|
||||||
|
|
@ -4269,7 +4269,7 @@ fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||||
const mod = f.object.dg.module;
|
const mod = f.object.dg.module;
|
||||||
const pl_op = f.air.instructions.items(.data)[inst].pl_op;
|
const pl_op = f.air.instructions.items(.data)[inst].pl_op;
|
||||||
const name = f.air.nullTerminatedString(pl_op.payload);
|
const name = f.air.nullTerminatedString(pl_op.payload);
|
||||||
const operand_is_undef = if (f.air.value(pl_op.operand, mod)) |v| v.isUndefDeep() else false;
|
const operand_is_undef = if (try f.air.value(pl_op.operand, mod)) |v| v.isUndefDeep() else false;
|
||||||
if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
|
if (!operand_is_undef) _ = try f.resolveInst(pl_op.operand);
|
||||||
|
|
||||||
try reap(f, inst, &.{pl_op.operand});
|
try reap(f, inst, &.{pl_op.operand});
|
||||||
|
|
@ -4735,7 +4735,7 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||||
try f.renderType(writer, Type.usize);
|
try f.renderType(writer, Type.usize);
|
||||||
try writer.writeByte(')');
|
try writer.writeByte(')');
|
||||||
}
|
}
|
||||||
try f.object.dg.renderValue(writer, condition_ty, f.air.value(item, mod).?, .Other);
|
try f.object.dg.renderValue(writer, condition_ty, (try f.air.value(item, mod)).?, .Other);
|
||||||
try writer.writeByte(':');
|
try writer.writeByte(':');
|
||||||
}
|
}
|
||||||
try writer.writeByte(' ');
|
try writer.writeByte(' ');
|
||||||
|
|
@ -5069,7 +5069,7 @@ fn airIsNull(
|
||||||
// operand is a regular pointer, test `operand !=/== NULL`
|
// operand is a regular pointer, test `operand !=/== NULL`
|
||||||
TypedValue{ .ty = optional_ty, .val = Value.null }
|
TypedValue{ .ty = optional_ty, .val = Value.null }
|
||||||
else if (payload_ty.zigTypeTag(mod) == .ErrorSet)
|
else if (payload_ty.zigTypeTag(mod) == .ErrorSet)
|
||||||
TypedValue{ .ty = payload_ty, .val = Value.zero }
|
TypedValue{ .ty = payload_ty, .val = try mod.intValue(payload_ty, 0) }
|
||||||
else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {
|
else if (payload_ty.isSlice(mod) and optional_ty.optionalReprIsPayload(mod)) rhs: {
|
||||||
try writer.writeAll(".ptr");
|
try writer.writeAll(".ptr");
|
||||||
const slice_ptr_ty = payload_ty.slicePtrFieldType(&slice_ptr_buf, mod);
|
const slice_ptr_ty = payload_ty.slicePtrFieldType(&slice_ptr_buf, mod);
|
||||||
|
|
@ -5325,7 +5325,7 @@ fn airFieldParentPtr(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||||
},
|
},
|
||||||
.end => {
|
.end => {
|
||||||
try f.writeCValue(writer, field_ptr_val, .Other);
|
try f.writeCValue(writer, field_ptr_val, .Other);
|
||||||
try writer.print(" - {}", .{try f.fmtIntLiteral(Type.usize, Value.one)});
|
try writer.print(" - {}", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5378,7 +5378,7 @@ fn fieldPtr(
|
||||||
.end => {
|
.end => {
|
||||||
try writer.writeByte('(');
|
try writer.writeByte('(');
|
||||||
try f.writeCValue(writer, container_ptr_val, .Other);
|
try f.writeCValue(writer, container_ptr_val, .Other);
|
||||||
try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, Value.one)});
|
try writer.print(" + {})", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))});
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5546,7 +5546,7 @@ fn airUnwrapErrUnionErr(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||||
else
|
else
|
||||||
try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
|
try f.writeCValueMember(writer, operand, .{ .identifier = "error" })
|
||||||
else
|
else
|
||||||
try f.object.dg.renderValue(writer, error_ty, Value.zero, .Initializer);
|
try f.object.dg.renderValue(writer, error_ty, try mod.intValue(error_ty, 0), .Initializer);
|
||||||
}
|
}
|
||||||
try writer.writeAll(";\n");
|
try writer.writeAll(";\n");
|
||||||
return local;
|
return local;
|
||||||
|
|
@ -5673,7 +5673,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||||
try f.writeCValueDeref(writer, operand);
|
try f.writeCValueDeref(writer, operand);
|
||||||
try writer.writeAll(" = ");
|
try writer.writeAll(" = ");
|
||||||
try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
|
try f.object.dg.renderValue(writer, error_ty, try mod.intValue(error_ty, 0), .Other);
|
||||||
try writer.writeAll(";\n ");
|
try writer.writeAll(";\n ");
|
||||||
|
|
||||||
return operand;
|
return operand;
|
||||||
|
|
@ -5681,7 +5681,7 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||||
try reap(f, inst, &.{ty_op.operand});
|
try reap(f, inst, &.{ty_op.operand});
|
||||||
try f.writeCValueDeref(writer, operand);
|
try f.writeCValueDeref(writer, operand);
|
||||||
try writer.writeAll(".error = ");
|
try writer.writeAll(".error = ");
|
||||||
try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
|
try f.object.dg.renderValue(writer, error_ty, try mod.intValue(error_ty, 0), .Other);
|
||||||
try writer.writeAll(";\n");
|
try writer.writeAll(";\n");
|
||||||
|
|
||||||
// Then return the payload pointer (only if it is used)
|
// Then return the payload pointer (only if it is used)
|
||||||
|
|
@ -5737,7 +5737,7 @@ fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||||
else
|
else
|
||||||
try f.writeCValueMember(writer, local, .{ .identifier = "error" });
|
try f.writeCValueMember(writer, local, .{ .identifier = "error" });
|
||||||
try a.assign(f, writer);
|
try a.assign(f, writer);
|
||||||
try f.object.dg.renderValue(writer, err_ty, Value.zero, .Other);
|
try f.object.dg.renderValue(writer, err_ty, try mod.intValue(err_ty, 0), .Other);
|
||||||
try a.end(f, writer);
|
try a.end(f, writer);
|
||||||
}
|
}
|
||||||
return local;
|
return local;
|
||||||
|
|
@ -5768,11 +5768,11 @@ fn airIsErr(f: *Function, inst: Air.Inst.Index, is_ptr: bool, operator: []const
|
||||||
else
|
else
|
||||||
try f.writeCValue(writer, operand, .Other)
|
try f.writeCValue(writer, operand, .Other)
|
||||||
else
|
else
|
||||||
try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
|
try f.object.dg.renderValue(writer, error_ty, try mod.intValue(error_ty, 0), .Other);
|
||||||
try writer.writeByte(' ');
|
try writer.writeByte(' ');
|
||||||
try writer.writeAll(operator);
|
try writer.writeAll(operator);
|
||||||
try writer.writeByte(' ');
|
try writer.writeByte(' ');
|
||||||
try f.object.dg.renderValue(writer, error_ty, Value.zero, .Other);
|
try f.object.dg.renderValue(writer, error_ty, try mod.intValue(error_ty, 0), .Other);
|
||||||
try writer.writeAll(";\n");
|
try writer.writeAll(";\n");
|
||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
|
|
@ -5798,7 +5798,7 @@ fn airArrayToSlice(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||||
} else if (array_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
} else if (array_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||||
try writer.writeAll("&(");
|
try writer.writeAll("&(");
|
||||||
try f.writeCValueDeref(writer, operand);
|
try f.writeCValueDeref(writer, operand);
|
||||||
try writer.print(")[{}]", .{try f.fmtIntLiteral(Type.usize, Value.zero)});
|
try writer.print(")[{}]", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 0))});
|
||||||
} else try f.writeCValue(writer, operand, .Initializer);
|
} else try f.writeCValue(writer, operand, .Initializer);
|
||||||
try writer.writeAll("; ");
|
try writer.writeAll("; ");
|
||||||
|
|
||||||
|
|
@ -6022,7 +6022,7 @@ fn airCmpBuiltinCall(
|
||||||
try writer.writeByte(')');
|
try writer.writeByte(')');
|
||||||
if (!ref_ret) try writer.print(" {s} {}", .{
|
if (!ref_ret) try writer.print(" {s} {}", .{
|
||||||
compareOperatorC(operator),
|
compareOperatorC(operator),
|
||||||
try f.fmtIntLiteral(Type.i32, Value.zero),
|
try f.fmtIntLiteral(Type.i32, try mod.intValue(Type.i32, 0)),
|
||||||
});
|
});
|
||||||
try writer.writeAll(";\n");
|
try writer.writeAll(";\n");
|
||||||
try v.end(f, inst, writer);
|
try v.end(f, inst, writer);
|
||||||
|
|
@ -6278,7 +6278,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
|
||||||
const value = try f.resolveInst(bin_op.rhs);
|
const value = try f.resolveInst(bin_op.rhs);
|
||||||
const elem_ty = f.typeOf(bin_op.rhs);
|
const elem_ty = f.typeOf(bin_op.rhs);
|
||||||
const elem_abi_size = elem_ty.abiSize(mod);
|
const elem_abi_size = elem_ty.abiSize(mod);
|
||||||
const val_is_undef = if (f.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep() else false;
|
const val_is_undef = if (try f.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep() else false;
|
||||||
const writer = f.object.writer();
|
const writer = f.object.writer();
|
||||||
|
|
||||||
if (val_is_undef) {
|
if (val_is_undef) {
|
||||||
|
|
@ -6326,7 +6326,7 @@ fn airMemset(f: *Function, inst: Air.Inst.Index, safety: bool) !CValue {
|
||||||
try writer.writeAll("for (");
|
try writer.writeAll("for (");
|
||||||
try f.writeCValue(writer, index, .Other);
|
try f.writeCValue(writer, index, .Other);
|
||||||
try writer.writeAll(" = ");
|
try writer.writeAll(" = ");
|
||||||
try f.object.dg.renderValue(writer, Type.usize, Value.zero, .Initializer);
|
try f.object.dg.renderValue(writer, Type.usize, try mod.intValue(Type.usize, 0), .Initializer);
|
||||||
try writer.writeAll("; ");
|
try writer.writeAll("; ");
|
||||||
try f.writeCValue(writer, index, .Other);
|
try f.writeCValue(writer, index, .Other);
|
||||||
try writer.writeAll(" != ");
|
try writer.writeAll(" != ");
|
||||||
|
|
@ -6677,27 +6677,27 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||||
std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
|
std.heap.stackFallback(@sizeOf(ExpectedContents), arena.allocator());
|
||||||
|
|
||||||
try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) {
|
try f.object.dg.renderValue(writer, scalar_ty, switch (reduce.operation) {
|
||||||
.Or, .Xor, .Add => Value.zero,
|
.Or, .Xor, .Add => try mod.intValue(scalar_ty, 0),
|
||||||
.And => switch (scalar_ty.zigTypeTag(mod)) {
|
.And => switch (scalar_ty.zigTypeTag(mod)) {
|
||||||
.Bool => Value.one,
|
.Bool => try mod.intValue(Type.comptime_int, 1),
|
||||||
else => switch (scalar_ty.intInfo(mod).signedness) {
|
else => switch (scalar_ty.intInfo(mod).signedness) {
|
||||||
.unsigned => try scalar_ty.maxIntScalar(mod),
|
.unsigned => try scalar_ty.maxIntScalar(mod),
|
||||||
.signed => Value.negative_one,
|
.signed => try mod.intValue(scalar_ty, -1),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.Min => switch (scalar_ty.zigTypeTag(mod)) {
|
.Min => switch (scalar_ty.zigTypeTag(mod)) {
|
||||||
.Bool => Value.one,
|
.Bool => try mod.intValue(Type.comptime_int, 1),
|
||||||
.Int => try scalar_ty.maxIntScalar(mod),
|
.Int => try scalar_ty.maxIntScalar(mod),
|
||||||
.Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target),
|
.Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
.Max => switch (scalar_ty.zigTypeTag(mod)) {
|
.Max => switch (scalar_ty.zigTypeTag(mod)) {
|
||||||
.Bool => Value.zero,
|
.Bool => try mod.intValue(scalar_ty, 0),
|
||||||
.Int => try scalar_ty.minInt(stack.get(), mod),
|
.Int => try scalar_ty.minInt(stack.get(), mod),
|
||||||
.Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target),
|
.Float => try Value.floatToValue(std.math.nan(f128), stack.get(), scalar_ty, target),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
},
|
},
|
||||||
.Mul => Value.one,
|
.Mul => try mod.intValue(Type.comptime_int, 1),
|
||||||
}, .Initializer);
|
}, .Initializer);
|
||||||
try writer.writeAll(";\n");
|
try writer.writeAll(";\n");
|
||||||
|
|
||||||
|
|
@ -7686,13 +7686,13 @@ const Vectorize = struct {
|
||||||
|
|
||||||
try writer.writeAll("for (");
|
try writer.writeAll("for (");
|
||||||
try f.writeCValue(writer, local, .Other);
|
try f.writeCValue(writer, local, .Other);
|
||||||
try writer.print(" = {d}; ", .{try f.fmtIntLiteral(Type.usize, Value.zero)});
|
try writer.print(" = {d}; ", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 0))});
|
||||||
try f.writeCValue(writer, local, .Other);
|
try f.writeCValue(writer, local, .Other);
|
||||||
try writer.print(" < {d}; ", .{
|
try writer.print(" < {d}; ", .{
|
||||||
try f.fmtIntLiteral(Type.usize, len_val),
|
try f.fmtIntLiteral(Type.usize, len_val),
|
||||||
});
|
});
|
||||||
try f.writeCValue(writer, local, .Other);
|
try f.writeCValue(writer, local, .Other);
|
||||||
try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(Type.usize, Value.one)});
|
try writer.print(" += {d}) {{\n", .{try f.fmtIntLiteral(Type.usize, try mod.intValue(Type.usize, 1))});
|
||||||
f.object.indent_writer.pushIndent();
|
f.object.indent_writer.pushIndent();
|
||||||
|
|
||||||
break :index .{ .index = local };
|
break :index .{ .index = local };
|
||||||
|
|
|
||||||
|
|
@ -2854,7 +2854,7 @@ pub const DeclGen = struct {
|
||||||
},
|
},
|
||||||
.Array => {
|
.Array => {
|
||||||
const elem_ty = t.childType(mod);
|
const elem_ty = t.childType(mod);
|
||||||
assert(elem_ty.onePossibleValue(mod) == null);
|
if (std.debug.runtime_safety) assert((try elem_ty.onePossibleValue(mod)) == null);
|
||||||
const elem_llvm_ty = try dg.lowerType(elem_ty);
|
const elem_llvm_ty = try dg.lowerType(elem_ty);
|
||||||
const total_len = t.arrayLen(mod) + @boolToInt(t.sentinel(mod) != null);
|
const total_len = t.arrayLen(mod) + @boolToInt(t.sentinel(mod) != null);
|
||||||
return elem_llvm_ty.arrayType(@intCast(c_uint, total_len));
|
return elem_llvm_ty.arrayType(@intCast(c_uint, total_len));
|
||||||
|
|
@ -3588,7 +3588,7 @@ pub const DeclGen = struct {
|
||||||
|
|
||||||
if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
|
if (!payload_type.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||||
// We use the error type directly as the type.
|
// We use the error type directly as the type.
|
||||||
const err_val = if (!is_pl) tv.val else Value.zero;
|
const err_val = if (!is_pl) tv.val else try mod.intValue(Type.anyerror, 0);
|
||||||
return dg.lowerValue(.{ .ty = Type.anyerror, .val = err_val });
|
return dg.lowerValue(.{ .ty = Type.anyerror, .val = err_val });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3596,7 +3596,7 @@ pub const DeclGen = struct {
|
||||||
const error_align = Type.anyerror.abiAlignment(mod);
|
const error_align = Type.anyerror.abiAlignment(mod);
|
||||||
const llvm_error_value = try dg.lowerValue(.{
|
const llvm_error_value = try dg.lowerValue(.{
|
||||||
.ty = Type.anyerror,
|
.ty = Type.anyerror,
|
||||||
.val = if (is_pl) Value.zero else tv.val,
|
.val = if (is_pl) try mod.intValue(Type.anyerror, 0) else tv.val,
|
||||||
});
|
});
|
||||||
const llvm_payload_value = try dg.lowerValue(.{
|
const llvm_payload_value = try dg.lowerValue(.{
|
||||||
.ty = payload_type,
|
.ty = payload_type,
|
||||||
|
|
@ -4476,7 +4476,7 @@ pub const FuncGen = struct {
|
||||||
const mod = self.dg.module;
|
const mod = self.dg.module;
|
||||||
const llvm_val = try self.resolveValue(.{
|
const llvm_val = try self.resolveValue(.{
|
||||||
.ty = self.typeOf(inst),
|
.ty = self.typeOf(inst),
|
||||||
.val = self.air.value(inst, mod).?,
|
.val = (try self.air.value(inst, mod)).?,
|
||||||
});
|
});
|
||||||
gop.value_ptr.* = llvm_val;
|
gop.value_ptr.* = llvm_val;
|
||||||
return llvm_val;
|
return llvm_val;
|
||||||
|
|
@ -6873,7 +6873,7 @@ pub const FuncGen = struct {
|
||||||
const err_union_ty = self.typeOf(ty_op.operand).childType(mod);
|
const err_union_ty = self.typeOf(ty_op.operand).childType(mod);
|
||||||
|
|
||||||
const payload_ty = err_union_ty.errorUnionPayload();
|
const payload_ty = err_union_ty.errorUnionPayload();
|
||||||
const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero });
|
const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = try mod.intValue(Type.anyerror, 0) });
|
||||||
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
|
||||||
_ = self.builder.buildStore(non_error_val, operand);
|
_ = self.builder.buildStore(non_error_val, operand);
|
||||||
return operand;
|
return operand;
|
||||||
|
|
@ -8203,7 +8203,7 @@ pub const FuncGen = struct {
|
||||||
const ptr_ty = self.typeOf(bin_op.lhs);
|
const ptr_ty = self.typeOf(bin_op.lhs);
|
||||||
const operand_ty = ptr_ty.childType(mod);
|
const operand_ty = ptr_ty.childType(mod);
|
||||||
|
|
||||||
const val_is_undef = if (self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep() else false;
|
const val_is_undef = if (try self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep() else false;
|
||||||
if (val_is_undef) {
|
if (val_is_undef) {
|
||||||
// Even if safety is disabled, we still emit a memset to undefined since it conveys
|
// Even if safety is disabled, we still emit a memset to undefined since it conveys
|
||||||
// extra information to LLVM. However, safety makes the difference between using
|
// extra information to LLVM. However, safety makes the difference between using
|
||||||
|
|
@ -8494,7 +8494,7 @@ pub const FuncGen = struct {
|
||||||
const dest_ptr = self.sliceOrArrayPtr(dest_slice, ptr_ty);
|
const dest_ptr = self.sliceOrArrayPtr(dest_slice, ptr_ty);
|
||||||
const is_volatile = ptr_ty.isVolatilePtr(mod);
|
const is_volatile = ptr_ty.isVolatilePtr(mod);
|
||||||
|
|
||||||
if (self.air.value(bin_op.rhs, mod)) |elem_val| {
|
if (try self.air.value(bin_op.rhs, mod)) |elem_val| {
|
||||||
if (elem_val.isUndefDeep()) {
|
if (elem_val.isUndefDeep()) {
|
||||||
// Even if safety is disabled, we still emit a memset to undefined since it conveys
|
// Even if safety is disabled, we still emit a memset to undefined since it conveys
|
||||||
// extra information to LLVM. However, safety makes the difference between using
|
// extra information to LLVM. However, safety makes the difference between using
|
||||||
|
|
@ -9323,7 +9323,7 @@ pub const FuncGen = struct {
|
||||||
|
|
||||||
var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined };
|
var indices: [2]*llvm.Value = .{ llvm_u32.constNull(), undefined };
|
||||||
for (elements, 0..) |elem, i| {
|
for (elements, 0..) |elem, i| {
|
||||||
if (result_ty.structFieldValueComptime(mod, i) != null) continue;
|
if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;
|
||||||
|
|
||||||
const llvm_elem = try self.resolveInst(elem);
|
const llvm_elem = try self.resolveInst(elem);
|
||||||
const llvm_i = llvmFieldIndex(result_ty, i, mod, &ptr_ty_buf).?;
|
const llvm_i = llvmFieldIndex(result_ty, i, mod, &ptr_ty_buf).?;
|
||||||
|
|
@ -9344,7 +9344,7 @@ pub const FuncGen = struct {
|
||||||
} else {
|
} else {
|
||||||
var result = llvm_result_ty.getUndef();
|
var result = llvm_result_ty.getUndef();
|
||||||
for (elements, 0..) |elem, i| {
|
for (elements, 0..) |elem, i| {
|
||||||
if (result_ty.structFieldValueComptime(mod, i) != null) continue;
|
if ((try result_ty.structFieldValueComptime(mod, i)) != null) continue;
|
||||||
|
|
||||||
const llvm_elem = try self.resolveInst(elem);
|
const llvm_elem = try self.resolveInst(elem);
|
||||||
const llvm_i = llvmFieldIndex(result_ty, i, mod, &ptr_ty_buf).?;
|
const llvm_i = llvmFieldIndex(result_ty, i, mod, &ptr_ty_buf).?;
|
||||||
|
|
|
||||||
|
|
@ -232,7 +232,7 @@ pub const DeclGen = struct {
|
||||||
/// Fetch the result-id for a previously generated instruction or constant.
|
/// Fetch the result-id for a previously generated instruction or constant.
|
||||||
fn resolve(self: *DeclGen, inst: Air.Inst.Ref) !IdRef {
|
fn resolve(self: *DeclGen, inst: Air.Inst.Ref) !IdRef {
|
||||||
const mod = self.module;
|
const mod = self.module;
|
||||||
if (self.air.value(inst, mod)) |val| {
|
if (try self.air.value(inst, mod)) |val| {
|
||||||
const ty = self.typeOf(inst);
|
const ty = self.typeOf(inst);
|
||||||
if (ty.zigTypeTag(mod) == .Fn) {
|
if (ty.zigTypeTag(mod) == .Fn) {
|
||||||
const fn_decl_index = switch (val.tag()) {
|
const fn_decl_index = switch (val.tag()) {
|
||||||
|
|
@ -584,7 +584,7 @@ pub const DeclGen = struct {
|
||||||
// TODO: Properly lower function pointers. For now we are going to hack around it and
|
// TODO: Properly lower function pointers. For now we are going to hack around it and
|
||||||
// just generate an empty pointer. Function pointers are represented by usize for now,
|
// just generate an empty pointer. Function pointers are represented by usize for now,
|
||||||
// though.
|
// though.
|
||||||
try self.addInt(Type.usize, Value.zero);
|
try self.addInt(Type.usize, Value.zero_usize);
|
||||||
// TODO: Add dependency
|
// TODO: Add dependency
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
|
|
@ -803,7 +803,7 @@ pub const DeclGen = struct {
|
||||||
.ErrorUnion => {
|
.ErrorUnion => {
|
||||||
const payload_ty = ty.errorUnionPayload();
|
const payload_ty = ty.errorUnionPayload();
|
||||||
const is_pl = val.errorUnionIsPayload();
|
const is_pl = val.errorUnionIsPayload();
|
||||||
const error_val = if (!is_pl) val else Value.zero;
|
const error_val = if (!is_pl) val else try mod.intValue(Type.anyerror, 0);
|
||||||
|
|
||||||
const eu_layout = dg.errorUnionLayout(payload_ty);
|
const eu_layout = dg.errorUnionLayout(payload_ty);
|
||||||
if (!eu_layout.payload_has_bits) {
|
if (!eu_layout.payload_has_bits) {
|
||||||
|
|
@ -2801,7 +2801,7 @@ pub const DeclGen = struct {
|
||||||
const value = try self.resolve(bin_op.rhs);
|
const value = try self.resolve(bin_op.rhs);
|
||||||
const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);
|
const ptr_ty_ref = try self.resolveType(ptr_ty, .direct);
|
||||||
|
|
||||||
const val_is_undef = if (self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep() else false;
|
const val_is_undef = if (try self.air.value(bin_op.rhs, mod)) |val| val.isUndefDeep() else false;
|
||||||
if (val_is_undef) {
|
if (val_is_undef) {
|
||||||
const undef = try self.spv.constUndef(ptr_ty_ref);
|
const undef = try self.spv.constUndef(ptr_ty_ref);
|
||||||
try self.store(ptr_ty, ptr, undef);
|
try self.store(ptr_ty, ptr, undef);
|
||||||
|
|
@ -3141,7 +3141,7 @@ pub const DeclGen = struct {
|
||||||
const label = IdRef{ .id = first_case_label.id + case_i };
|
const label = IdRef{ .id = first_case_label.id + case_i };
|
||||||
|
|
||||||
for (items) |item| {
|
for (items) |item| {
|
||||||
const value = self.air.value(item, mod) orelse {
|
const value = (try self.air.value(item, mod)) orelse {
|
||||||
return self.todo("switch on runtime value???", .{});
|
return self.todo("switch on runtime value???", .{});
|
||||||
};
|
};
|
||||||
const int_val = switch (cond_ty.zigTypeTag(mod)) {
|
const int_val = switch (cond_ty.zigTypeTag(mod)) {
|
||||||
|
|
|
||||||
44
src/type.zig
44
src/type.zig
|
|
@ -3377,7 +3377,7 @@ pub const Type = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For vectors, returns the element type. Otherwise returns self.
|
/// For vectors, returns the element type. Otherwise returns self.
|
||||||
pub fn scalarType(ty: Type, mod: *const Module) Type {
|
pub fn scalarType(ty: Type, mod: *Module) Type {
|
||||||
return switch (ty.zigTypeTag(mod)) {
|
return switch (ty.zigTypeTag(mod)) {
|
||||||
.Vector => ty.childType(mod),
|
.Vector => ty.childType(mod),
|
||||||
else => ty,
|
else => ty,
|
||||||
|
|
@ -3941,13 +3941,13 @@ pub const Type = struct {
|
||||||
|
|
||||||
/// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which
|
/// During semantic analysis, instead call `Sema.typeHasOnePossibleValue` which
|
||||||
/// resolves field types rather than asserting they are already resolved.
|
/// resolves field types rather than asserting they are already resolved.
|
||||||
pub fn onePossibleValue(starting_type: Type, mod: *const Module) ?Value {
|
pub fn onePossibleValue(starting_type: Type, mod: *Module) !?Value {
|
||||||
var ty = starting_type;
|
var ty = starting_type;
|
||||||
|
|
||||||
if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
|
if (ty.ip_index != .none) switch (mod.intern_pool.indexToKey(ty.ip_index)) {
|
||||||
.int_type => |int_type| {
|
.int_type => |int_type| {
|
||||||
if (int_type.bits == 0) {
|
if (int_type.bits == 0) {
|
||||||
return Value.zero;
|
return try mod.intValue(ty, 0);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -3956,13 +3956,13 @@ pub const Type = struct {
|
||||||
.array_type => |array_type| {
|
.array_type => |array_type| {
|
||||||
if (array_type.len == 0)
|
if (array_type.len == 0)
|
||||||
return Value.initTag(.empty_array);
|
return Value.initTag(.empty_array);
|
||||||
if (array_type.child.toType().onePossibleValue(mod) != null)
|
if ((try array_type.child.toType().onePossibleValue(mod)) != null)
|
||||||
return Value.initTag(.the_only_possible_value);
|
return Value.initTag(.the_only_possible_value);
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
.vector_type => |vector_type| {
|
.vector_type => |vector_type| {
|
||||||
if (vector_type.len == 0) return Value.initTag(.empty_array);
|
if (vector_type.len == 0) return Value.initTag(.empty_array);
|
||||||
if (vector_type.child.toType().onePossibleValue(mod)) |v| return v;
|
if (try vector_type.child.toType().onePossibleValue(mod)) |v| return v;
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
.opt_type => |child| {
|
.opt_type => |child| {
|
||||||
|
|
@ -4055,7 +4055,7 @@ pub const Type = struct {
|
||||||
assert(s.haveFieldTypes());
|
assert(s.haveFieldTypes());
|
||||||
for (s.fields.values()) |field| {
|
for (s.fields.values()) |field| {
|
||||||
if (field.is_comptime) continue;
|
if (field.is_comptime) continue;
|
||||||
if (field.ty.onePossibleValue(mod) != null) continue;
|
if ((try field.ty.onePossibleValue(mod)) != null) continue;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return Value.initTag(.empty_struct_value);
|
return Value.initTag(.empty_struct_value);
|
||||||
|
|
@ -4066,7 +4066,7 @@ pub const Type = struct {
|
||||||
for (tuple.values, 0..) |val, i| {
|
for (tuple.values, 0..) |val, i| {
|
||||||
const is_comptime = val.ip_index != .unreachable_value;
|
const is_comptime = val.ip_index != .unreachable_value;
|
||||||
if (is_comptime) continue;
|
if (is_comptime) continue;
|
||||||
if (tuple.types[i].onePossibleValue(mod) != null) continue;
|
if ((try tuple.types[i].onePossibleValue(mod)) != null) continue;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return Value.initTag(.empty_struct_value);
|
return Value.initTag(.empty_struct_value);
|
||||||
|
|
@ -4089,7 +4089,7 @@ pub const Type = struct {
|
||||||
switch (enum_full.fields.count()) {
|
switch (enum_full.fields.count()) {
|
||||||
0 => return Value.@"unreachable",
|
0 => return Value.@"unreachable",
|
||||||
1 => if (enum_full.values.count() == 0) {
|
1 => if (enum_full.values.count() == 0) {
|
||||||
return Value.zero; // auto-numbered
|
return try mod.intValue(ty, 0); // auto-numbered
|
||||||
} else {
|
} else {
|
||||||
return enum_full.values.keys()[0];
|
return enum_full.values.keys()[0];
|
||||||
},
|
},
|
||||||
|
|
@ -4100,24 +4100,24 @@ pub const Type = struct {
|
||||||
const enum_simple = ty.castTag(.enum_simple).?.data;
|
const enum_simple = ty.castTag(.enum_simple).?.data;
|
||||||
switch (enum_simple.fields.count()) {
|
switch (enum_simple.fields.count()) {
|
||||||
0 => return Value.@"unreachable",
|
0 => return Value.@"unreachable",
|
||||||
1 => return Value.zero,
|
1 => return try mod.intValue(ty, 0),
|
||||||
else => return null,
|
else => return null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.enum_nonexhaustive => {
|
.enum_nonexhaustive => {
|
||||||
const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
|
const tag_ty = ty.castTag(.enum_nonexhaustive).?.data.tag_ty;
|
||||||
if (!tag_ty.hasRuntimeBits(mod)) {
|
if (!tag_ty.hasRuntimeBits(mod)) {
|
||||||
return Value.zero;
|
return try mod.intValue(ty, 0);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.@"union", .union_safety_tagged, .union_tagged => {
|
.@"union", .union_safety_tagged, .union_tagged => {
|
||||||
const union_obj = ty.cast(Payload.Union).?.data;
|
const union_obj = ty.cast(Payload.Union).?.data;
|
||||||
const tag_val = union_obj.tag_ty.onePossibleValue(mod) orelse return null;
|
const tag_val = (try union_obj.tag_ty.onePossibleValue(mod)) orelse return null;
|
||||||
if (union_obj.fields.count() == 0) return Value.@"unreachable";
|
if (union_obj.fields.count() == 0) return Value.@"unreachable";
|
||||||
const only_field = union_obj.fields.values()[0];
|
const only_field = union_obj.fields.values()[0];
|
||||||
const val_val = only_field.ty.onePossibleValue(mod) orelse return null;
|
const val_val = (try only_field.ty.onePossibleValue(mod)) orelse return null;
|
||||||
_ = tag_val;
|
_ = tag_val;
|
||||||
_ = val_val;
|
_ = val_val;
|
||||||
return Value.initTag(.empty_struct_value);
|
return Value.initTag(.empty_struct_value);
|
||||||
|
|
@ -4128,7 +4128,7 @@ pub const Type = struct {
|
||||||
.array => {
|
.array => {
|
||||||
if (ty.arrayLen(mod) == 0)
|
if (ty.arrayLen(mod) == 0)
|
||||||
return Value.initTag(.empty_array);
|
return Value.initTag(.empty_array);
|
||||||
if (ty.childType(mod).onePossibleValue(mod) != null)
|
if ((try ty.childType(mod).onePossibleValue(mod)) != null)
|
||||||
return Value.initTag(.the_only_possible_value);
|
return Value.initTag(.the_only_possible_value);
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
|
@ -4365,8 +4365,8 @@ pub const Type = struct {
|
||||||
/// Asserts that the type is an integer.
|
/// Asserts that the type is an integer.
|
||||||
pub fn minIntScalar(ty: Type, mod: *Module) !Value {
|
pub fn minIntScalar(ty: Type, mod: *Module) !Value {
|
||||||
const info = ty.intInfo(mod);
|
const info = ty.intInfo(mod);
|
||||||
if (info.signedness == .unsigned) return Value.zero;
|
if (info.signedness == .unsigned) return mod.intValue(ty, 0);
|
||||||
if (info.bits == 0) return Value.negative_one;
|
if (info.bits == 0) return mod.intValue(ty, -1);
|
||||||
|
|
||||||
if (std.math.cast(u6, info.bits - 1)) |shift| {
|
if (std.math.cast(u6, info.bits - 1)) |shift| {
|
||||||
const n = @as(i64, std.math.minInt(i64)) >> (63 - shift);
|
const n = @as(i64, std.math.minInt(i64)) >> (63 - shift);
|
||||||
|
|
@ -4392,17 +4392,17 @@ pub const Type = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Asserts that the type is an integer.
|
/// Asserts that the type is an integer.
|
||||||
pub fn maxIntScalar(self: Type, mod: *Module) !Value {
|
pub fn maxIntScalar(ty: Type, mod: *Module) !Value {
|
||||||
const info = self.intInfo(mod);
|
const info = ty.intInfo(mod);
|
||||||
|
|
||||||
switch (info.bits) {
|
switch (info.bits) {
|
||||||
0 => return switch (info.signedness) {
|
0 => return switch (info.signedness) {
|
||||||
.signed => Value.negative_one,
|
.signed => mod.intValue(ty, -1),
|
||||||
.unsigned => Value.zero,
|
.unsigned => mod.intValue(ty, 0),
|
||||||
},
|
},
|
||||||
1 => return switch (info.signedness) {
|
1 => return switch (info.signedness) {
|
||||||
.signed => Value.zero,
|
.signed => mod.intValue(ty, 0),
|
||||||
.unsigned => Value.one,
|
.unsigned => mod.intValue(ty, 0),
|
||||||
},
|
},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
|
@ -4662,7 +4662,7 @@ pub const Type = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn structFieldValueComptime(ty: Type, mod: *const Module, index: usize) ?Value {
|
pub fn structFieldValueComptime(ty: Type, mod: *Module, index: usize) !?Value {
|
||||||
switch (ty.tag()) {
|
switch (ty.tag()) {
|
||||||
.@"struct" => {
|
.@"struct" => {
|
||||||
const struct_obj = ty.castTag(.@"struct").?.data;
|
const struct_obj = ty.castTag(.@"struct").?.data;
|
||||||
|
|
|
||||||
|
|
@ -1022,7 +1022,7 @@ pub const Value = struct {
|
||||||
if (opt_val) |some| {
|
if (opt_val) |some| {
|
||||||
return some.writeToMemory(child, mod, buffer);
|
return some.writeToMemory(child, mod, buffer);
|
||||||
} else {
|
} else {
|
||||||
return writeToMemory(Value.zero, Type.usize, mod, buffer);
|
return writeToMemory(try mod.intValue(Type.usize, 0), Type.usize, mod, buffer);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => return error.Unimplemented,
|
else => return error.Unimplemented,
|
||||||
|
|
@ -1124,7 +1124,7 @@ pub const Value = struct {
|
||||||
.Packed => {
|
.Packed => {
|
||||||
const field_index = ty.unionTagFieldIndex(val.unionTag(), mod);
|
const field_index = ty.unionTagFieldIndex(val.unionTag(), mod);
|
||||||
const field_type = ty.unionFields().values()[field_index.?].ty;
|
const field_type = ty.unionFields().values()[field_index.?].ty;
|
||||||
const field_val = val.fieldValue(field_type, mod, field_index.?);
|
const field_val = try val.fieldValue(field_type, mod, field_index.?);
|
||||||
|
|
||||||
return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset);
|
return field_val.writeToPackedMemory(field_type, mod, buffer, bit_offset);
|
||||||
},
|
},
|
||||||
|
|
@ -1141,7 +1141,7 @@ pub const Value = struct {
|
||||||
if (opt_val) |some| {
|
if (opt_val) |some| {
|
||||||
return some.writeToPackedMemory(child, mod, buffer, bit_offset);
|
return some.writeToPackedMemory(child, mod, buffer, bit_offset);
|
||||||
} else {
|
} else {
|
||||||
return writeToPackedMemory(Value.zero, Type.usize, mod, buffer, bit_offset);
|
return writeToPackedMemory(try mod.intValue(Type.usize, 0), Type.usize, mod, buffer, bit_offset);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => @panic("TODO implement writeToPackedMemory for more types"),
|
else => @panic("TODO implement writeToPackedMemory for more types"),
|
||||||
|
|
@ -1173,7 +1173,7 @@ pub const Value = struct {
|
||||||
const int_info = ty.intInfo(mod);
|
const int_info = ty.intInfo(mod);
|
||||||
const bits = int_info.bits;
|
const bits = int_info.bits;
|
||||||
const byte_count = (bits + 7) / 8;
|
const byte_count = (bits + 7) / 8;
|
||||||
if (bits == 0 or buffer.len == 0) return Value.zero;
|
if (bits == 0 or buffer.len == 0) return mod.intValue(ty, 0);
|
||||||
|
|
||||||
if (bits <= 64) switch (int_info.signedness) { // Fast path for integers <= u64
|
if (bits <= 64) switch (int_info.signedness) { // Fast path for integers <= u64
|
||||||
.signed => {
|
.signed => {
|
||||||
|
|
@ -1290,12 +1290,12 @@ pub const Value = struct {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.Int, .Enum => {
|
.Int, .Enum => {
|
||||||
if (buffer.len == 0) return Value.zero;
|
if (buffer.len == 0) return mod.intValue(ty, 0);
|
||||||
const int_info = ty.intInfo(mod);
|
const int_info = ty.intInfo(mod);
|
||||||
const abi_size = @intCast(usize, ty.abiSize(mod));
|
const abi_size = @intCast(usize, ty.abiSize(mod));
|
||||||
|
|
||||||
const bits = int_info.bits;
|
const bits = int_info.bits;
|
||||||
if (bits == 0) return Value.zero;
|
if (bits == 0) return mod.intValue(ty, 0);
|
||||||
if (bits <= 64) switch (int_info.signedness) { // Fast path for integers <= u64
|
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)),
|
.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)),
|
.unsigned => return mod.intValue(ty, std.mem.readVarPackedInt(u64, buffer, bit_offset, bits, endian, .unsigned)),
|
||||||
|
|
@ -2091,11 +2091,11 @@ pub const Value = struct {
|
||||||
// .the_one_possible_value,
|
// .the_one_possible_value,
|
||||||
// .aggregate,
|
// .aggregate,
|
||||||
// Note that we already checked above for matching tags, e.g. both .aggregate.
|
// Note that we already checked above for matching tags, e.g. both .aggregate.
|
||||||
return ty.onePossibleValue(mod) != null;
|
return (try ty.onePossibleValue(mod)) != null;
|
||||||
},
|
},
|
||||||
.Union => {
|
.Union => {
|
||||||
// Here we have to check for value equality, as-if `a` has been coerced to `ty`.
|
// Here we have to check for value equality, as-if `a` has been coerced to `ty`.
|
||||||
if (ty.onePossibleValue(mod) != null) {
|
if ((try ty.onePossibleValue(mod)) != null) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (a_ty.castTag(.anon_struct)) |payload| {
|
if (a_ty.castTag(.anon_struct)) |payload| {
|
||||||
|
|
@ -2604,7 +2604,7 @@ pub const Value = struct {
|
||||||
if (data.container_ptr.pointerDecl()) |decl_index| {
|
if (data.container_ptr.pointerDecl()) |decl_index| {
|
||||||
const container_decl = mod.declPtr(decl_index);
|
const container_decl = mod.declPtr(decl_index);
|
||||||
const field_type = data.container_ty.structFieldType(data.field_index);
|
const field_type = data.container_ty.structFieldType(data.field_index);
|
||||||
const field_val = container_decl.val.fieldValue(field_type, mod, data.field_index);
|
const field_val = try container_decl.val.fieldValue(field_type, mod, data.field_index);
|
||||||
return field_val.elemValue(mod, index);
|
return field_val.elemValue(mod, index);
|
||||||
} else unreachable;
|
} else unreachable;
|
||||||
},
|
},
|
||||||
|
|
@ -2723,7 +2723,7 @@ pub const Value = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fieldValue(val: Value, ty: Type, mod: *const Module, index: usize) Value {
|
pub fn fieldValue(val: Value, ty: Type, mod: *Module, index: usize) !Value {
|
||||||
switch (val.ip_index) {
|
switch (val.ip_index) {
|
||||||
.undef => return Value.undef,
|
.undef => return Value.undef,
|
||||||
.none => switch (val.tag()) {
|
.none => switch (val.tag()) {
|
||||||
|
|
@ -2737,14 +2737,14 @@ pub const Value = struct {
|
||||||
return payload.val;
|
return payload.val;
|
||||||
},
|
},
|
||||||
|
|
||||||
.the_only_possible_value => return ty.onePossibleValue(mod).?,
|
.the_only_possible_value => return (try ty.onePossibleValue(mod)).?,
|
||||||
|
|
||||||
.empty_struct_value => {
|
.empty_struct_value => {
|
||||||
if (ty.isSimpleTupleOrAnonStruct()) {
|
if (ty.isSimpleTupleOrAnonStruct()) {
|
||||||
const tuple = ty.tupleFields();
|
const tuple = ty.tupleFields();
|
||||||
return tuple.values[index];
|
return tuple.values[index];
|
||||||
}
|
}
|
||||||
if (ty.structFieldValueComptime(mod, index)) |some| {
|
if (try ty.structFieldValueComptime(mod, index)) |some| {
|
||||||
return some;
|
return some;
|
||||||
}
|
}
|
||||||
unreachable;
|
unreachable;
|
||||||
|
|
@ -2968,7 +2968,7 @@ pub const Value = struct {
|
||||||
switch (val.ip_index) {
|
switch (val.ip_index) {
|
||||||
.undef => return val,
|
.undef => return val,
|
||||||
.none => switch (val.tag()) {
|
.none => switch (val.tag()) {
|
||||||
.the_only_possible_value => return Value.zero, // for i0, u0
|
.the_only_possible_value => return Value.float_zero, // for i0, u0
|
||||||
.lazy_align => {
|
.lazy_align => {
|
||||||
const ty = val.castTag(.lazy_align).?.data;
|
const ty = val.castTag(.lazy_align).?.data;
|
||||||
if (opt_sema) |sema| {
|
if (opt_sema) |sema| {
|
||||||
|
|
@ -3402,7 +3402,7 @@ pub const Value = struct {
|
||||||
if (lhs.isUndef() or rhs.isUndef()) return Value.undef;
|
if (lhs.isUndef() or rhs.isUndef()) return Value.undef;
|
||||||
|
|
||||||
const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod);
|
const anded = try bitwiseAnd(lhs, rhs, ty, arena, mod);
|
||||||
const all_ones = if (ty.isSignedInt(mod)) Value.negative_one else try ty.maxIntScalar(mod);
|
const all_ones = if (ty.isSignedInt(mod)) try mod.intValue(ty, -1) else try ty.maxIntScalar(mod);
|
||||||
return bitwiseXor(anded, all_ones, ty, arena, mod);
|
return bitwiseXor(anded, all_ones, ty, arena, mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3803,7 +3803,7 @@ pub const Value = struct {
|
||||||
bits: u16,
|
bits: u16,
|
||||||
mod: *Module,
|
mod: *Module,
|
||||||
) !Value {
|
) !Value {
|
||||||
if (bits == 0) return Value.zero;
|
if (bits == 0) return mod.intValue(ty, 0);
|
||||||
|
|
||||||
var val_space: Value.BigIntSpace = undefined;
|
var val_space: Value.BigIntSpace = undefined;
|
||||||
const val_bigint = val.toBigInt(&val_space, mod);
|
const val_bigint = val.toBigInt(&val_space, mod);
|
||||||
|
|
@ -4011,9 +4011,9 @@ pub const Value = struct {
|
||||||
// The shift is enough to remove all the bits from the number, which means the
|
// The shift is enough to remove all the bits from the number, which means the
|
||||||
// result is 0 or -1 depending on the sign.
|
// result is 0 or -1 depending on the sign.
|
||||||
if (lhs_bigint.positive) {
|
if (lhs_bigint.positive) {
|
||||||
return Value.zero;
|
return mod.intValue(ty, 0);
|
||||||
} else {
|
} else {
|
||||||
return Value.negative_one;
|
return mod.intValue(ty, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5151,10 +5151,9 @@ pub const Value = struct {
|
||||||
|
|
||||||
pub const BigIntSpace = InternPool.Key.Int.Storage.BigIntSpace;
|
pub const BigIntSpace = InternPool.Key.Int.Storage.BigIntSpace;
|
||||||
|
|
||||||
pub const zero: Value = .{ .ip_index = .zero, .legacy = undefined };
|
pub const zero_usize: Value = .{ .ip_index = .zero_usize, .legacy = undefined };
|
||||||
pub const one: Value = .{ .ip_index = .one, .legacy = undefined };
|
|
||||||
pub const negative_one: Value = .{ .ip_index = .negative_one, .legacy = undefined };
|
|
||||||
pub const undef: Value = .{ .ip_index = .undef, .legacy = undefined };
|
pub const undef: Value = .{ .ip_index = .undef, .legacy = undefined };
|
||||||
|
pub const float_zero: Value = .{ .ip_index = .zero, .legacy = undefined }; // TODO: replace this!
|
||||||
pub const @"void": Value = .{ .ip_index = .void_value, .legacy = undefined };
|
pub const @"void": Value = .{ .ip_index = .void_value, .legacy = undefined };
|
||||||
pub const @"null": Value = .{ .ip_index = .null_value, .legacy = undefined };
|
pub const @"null": Value = .{ .ip_index = .null_value, .legacy = undefined };
|
||||||
pub const @"false": Value = .{ .ip_index = .bool_false, .legacy = undefined };
|
pub const @"false": Value = .{ .ip_index = .bool_false, .legacy = undefined };
|
||||||
|
|
@ -5169,7 +5168,9 @@ pub const Value = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn boolToInt(x: bool) Value {
|
pub fn boolToInt(x: bool) Value {
|
||||||
return if (x) Value.one else Value.zero;
|
const zero: Value = .{ .ip_index = .zero, .legacy = undefined };
|
||||||
|
const one: Value = .{ .ip_index = .one, .legacy = undefined };
|
||||||
|
return if (x) one else zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const RuntimeIndex = enum(u32) {
|
pub const RuntimeIndex = enum(u32) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue