mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 04:48:20 +00:00
Sema: make overflow arithmetic builtins return tuples
This commit is contained in:
parent
af9a9a1374
commit
54160e7f6a
@ -2505,7 +2505,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
|
||||
.err_union_code,
|
||||
.err_union_code_ptr,
|
||||
.ptr_type,
|
||||
.overflow_arithmetic_ptr,
|
||||
.enum_literal,
|
||||
.merge_error_sets,
|
||||
.error_union_type,
|
||||
@ -2543,7 +2542,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
|
||||
.type_info,
|
||||
.size_of,
|
||||
.bit_size_of,
|
||||
.log2_int_type,
|
||||
.typeof_log2_int_type,
|
||||
.ptr_to_int,
|
||||
.align_of,
|
||||
@ -8236,21 +8234,7 @@ fn builtinCall(
|
||||
.add_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .add_with_overflow),
|
||||
.sub_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .sub_with_overflow),
|
||||
.mul_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .mul_with_overflow),
|
||||
.shl_with_overflow => {
|
||||
const int_type = try typeExpr(gz, scope, params[0]);
|
||||
const log2_int_type = try gz.addUnNode(.log2_int_type, int_type, params[0]);
|
||||
const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]);
|
||||
const lhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[1]);
|
||||
const rhs = try expr(gz, scope, .{ .rl = .{ .ty = log2_int_type } }, params[2]);
|
||||
const ptr = try expr(gz, scope, .{ .rl = .{ .ty = ptr_type } }, params[3]);
|
||||
const result = try gz.addExtendedPayload(.shl_with_overflow, Zir.Inst.OverflowArithmetic{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.lhs = lhs,
|
||||
.rhs = rhs,
|
||||
.ptr = ptr,
|
||||
});
|
||||
return rvalue(gz, ri, result, node);
|
||||
},
|
||||
.shl_with_overflow => return overflowArithmetic(gz, scope, ri, node, params, .shl_with_overflow),
|
||||
|
||||
.atomic_load => {
|
||||
const result = try gz.addPlNode(.atomic_load, node, Zir.Inst.AtomicLoad{
|
||||
@ -8691,16 +8675,12 @@ fn overflowArithmetic(
|
||||
params: []const Ast.Node.Index,
|
||||
tag: Zir.Inst.Extended,
|
||||
) InnerError!Zir.Inst.Ref {
|
||||
const int_type = try typeExpr(gz, scope, params[0]);
|
||||
const ptr_type = try gz.addUnNode(.overflow_arithmetic_ptr, int_type, params[0]);
|
||||
const lhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[1]);
|
||||
const rhs = try expr(gz, scope, .{ .rl = .{ .ty = int_type } }, params[2]);
|
||||
const ptr = try expr(gz, scope, .{ .rl = .{ .ty = ptr_type } }, params[3]);
|
||||
const result = try gz.addExtendedPayload(tag, Zir.Inst.OverflowArithmetic{
|
||||
const lhs = try expr(gz, scope, .{ .rl = .none }, params[0]);
|
||||
const rhs = try expr(gz, scope, .{ .rl = .none }, params[1]);
|
||||
const result = try gz.addExtendedPayload(tag, Zir.Inst.BinNode{
|
||||
.node = gz.nodeIndexToRelative(node),
|
||||
.lhs = lhs,
|
||||
.rhs = rhs,
|
||||
.ptr = ptr,
|
||||
});
|
||||
return rvalue(gz, ri, result, node);
|
||||
}
|
||||
|
||||
@ -1510,26 +1510,6 @@ fn walkInstruction(
|
||||
|
||||
// return operand;
|
||||
// },
|
||||
.overflow_arithmetic_ptr => {
|
||||
const un_node = data[inst_index].un_node;
|
||||
|
||||
const elem_type_ref = try self.walkRef(file, parent_scope, parent_src, un_node.operand, false);
|
||||
const type_slot_index = self.types.items.len;
|
||||
try self.types.append(self.arena, .{
|
||||
.Pointer = .{
|
||||
.size = .One,
|
||||
.child = elem_type_ref.expr,
|
||||
.is_mutable = true,
|
||||
.is_volatile = false,
|
||||
.is_allowzero = false,
|
||||
},
|
||||
});
|
||||
|
||||
return DocData.WalkResult{
|
||||
.typeRef = .{ .type = @enumToInt(Ref.type_type) },
|
||||
.expr = .{ .type = type_slot_index },
|
||||
};
|
||||
},
|
||||
.ptr_type => {
|
||||
const ptr = data[inst_index].ptr_type;
|
||||
const extra = file.zir.extraData(Zir.Inst.PtrType, ptr.payload_index);
|
||||
|
||||
@ -154,7 +154,7 @@ pub const list = list: {
|
||||
"@addWithOverflow",
|
||||
.{
|
||||
.tag = .add_with_overflow,
|
||||
.param_count = 4,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
.{
|
||||
@ -636,7 +636,7 @@ pub const list = list: {
|
||||
"@mulWithOverflow",
|
||||
.{
|
||||
.tag = .mul_with_overflow,
|
||||
.param_count = 4,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
.{
|
||||
@ -741,7 +741,7 @@ pub const list = list: {
|
||||
"@shlWithOverflow",
|
||||
.{
|
||||
.tag = .shl_with_overflow,
|
||||
.param_count = 4,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
.{
|
||||
@ -889,7 +889,7 @@ pub const list = list: {
|
||||
"@subWithOverflow",
|
||||
.{
|
||||
.tag = .sub_with_overflow,
|
||||
.param_count = 4,
|
||||
.param_count = 2,
|
||||
},
|
||||
},
|
||||
.{
|
||||
|
||||
166
src/Sema.zig
166
src/Sema.zig
@ -971,7 +971,6 @@ fn analyzeBodyInner(
|
||||
.optional_payload_unsafe_ptr => try sema.zirOptionalPayloadPtr(block, inst, false),
|
||||
.optional_type => try sema.zirOptionalType(block, inst),
|
||||
.ptr_type => try sema.zirPtrType(block, inst),
|
||||
.overflow_arithmetic_ptr => try sema.zirOverflowArithmeticPtr(block, inst),
|
||||
.ref => try sema.zirRef(block, inst),
|
||||
.ret_err_value_code => try sema.zirRetErrValueCode(inst),
|
||||
.shr => try sema.zirShr(block, inst, .shr),
|
||||
@ -993,7 +992,6 @@ fn analyzeBodyInner(
|
||||
.bit_size_of => try sema.zirBitSizeOf(block, inst),
|
||||
.typeof => try sema.zirTypeof(block, inst),
|
||||
.typeof_builtin => try sema.zirTypeofBuiltin(block, inst),
|
||||
.log2_int_type => try sema.zirLog2IntType(block, inst),
|
||||
.typeof_log2_int_type => try sema.zirTypeofLog2IntType(block, inst),
|
||||
.xor => try sema.zirBitwise(block, inst, .xor),
|
||||
.struct_init_empty => try sema.zirStructInitEmpty(block, inst),
|
||||
@ -11762,7 +11760,7 @@ fn zirShl(
|
||||
if (scalar_ty.zigTypeTag() == .ComptimeInt) {
|
||||
break :val shifted.wrapped_result;
|
||||
}
|
||||
if (shifted.overflowed.compareAllWithZero(.eq)) {
|
||||
if (shifted.overflow_bit.compareAllWithZero(.eq)) {
|
||||
break :val shifted.wrapped_result;
|
||||
}
|
||||
return sema.fail(block, src, "operation caused overflow", .{});
|
||||
@ -13783,24 +13781,37 @@ fn zirOverflowArithmetic(
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const extra = sema.code.extraData(Zir.Inst.OverflowArithmetic, extended.operand).data;
|
||||
const extra = sema.code.extraData(Zir.Inst.BinNode, extended.operand).data;
|
||||
const src = LazySrcLoc.nodeOffset(extra.node);
|
||||
|
||||
const lhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = extra.node };
|
||||
const rhs_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = extra.node };
|
||||
const ptr_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = extra.node };
|
||||
|
||||
const lhs = try sema.resolveInst(extra.lhs);
|
||||
const rhs = try sema.resolveInst(extra.rhs);
|
||||
const ptr = try sema.resolveInst(extra.ptr);
|
||||
const uncasted_lhs = try sema.resolveInst(extra.lhs);
|
||||
const uncasted_rhs = try sema.resolveInst(extra.rhs);
|
||||
|
||||
const lhs_ty = sema.typeOf(lhs);
|
||||
const rhs_ty = sema.typeOf(rhs);
|
||||
const lhs_ty = sema.typeOf(uncasted_lhs);
|
||||
const rhs_ty = sema.typeOf(uncasted_rhs);
|
||||
const mod = sema.mod;
|
||||
|
||||
// Note, the types of lhs/rhs (also for shifting)/ptr are already correct as ensured by astgen.
|
||||
try sema.checkVectorizableBinaryOperands(block, src, lhs_ty, rhs_ty, lhs_src, rhs_src);
|
||||
const dest_ty = lhs_ty;
|
||||
|
||||
const instructions = &[_]Air.Inst.Ref{ uncasted_lhs, uncasted_rhs };
|
||||
const dest_ty = if (zir_tag == .shl_with_overflow)
|
||||
lhs_ty
|
||||
else
|
||||
try sema.resolvePeerTypes(block, src, instructions, .{
|
||||
.override = &[_]LazySrcLoc{ lhs_src, rhs_src },
|
||||
});
|
||||
|
||||
const rhs_dest_ty = if (zir_tag == .shl_with_overflow)
|
||||
try sema.log2IntType(block, lhs_ty, src)
|
||||
else
|
||||
dest_ty;
|
||||
|
||||
const lhs = try sema.coerce(block, dest_ty, uncasted_lhs, lhs_src);
|
||||
const rhs = try sema.coerce(block, rhs_dest_ty, uncasted_rhs, rhs_src);
|
||||
|
||||
if (dest_ty.scalarType().zigTypeTag() != .Int) {
|
||||
return sema.fail(block, src, "expected vector of integers or integer tag type, found '{}'", .{dest_ty.fmt(mod)});
|
||||
}
|
||||
@ -13809,14 +13820,11 @@ fn zirOverflowArithmetic(
|
||||
const maybe_rhs_val = try sema.resolveMaybeUndefVal(rhs);
|
||||
|
||||
const tuple_ty = try sema.overflowArithmeticTupleType(dest_ty);
|
||||
// TODO: Remove and use `ov_ty` instead.
|
||||
// This is a temporary type used until overflow arithmetic properly returns `u1` instead of `bool`.
|
||||
const overflowed_ty = if (dest_ty.zigTypeTag() == .Vector) try Type.vector(sema.arena, dest_ty.vectorLen(), Type.bool) else Type.bool;
|
||||
|
||||
const result: struct {
|
||||
/// TODO: Rename to `overflow_bit` and make of type `u1`.
|
||||
overflowed: Air.Inst.Ref,
|
||||
wrapped: Air.Inst.Ref,
|
||||
var result: struct {
|
||||
inst: Air.Inst.Ref = .none,
|
||||
wrapped: Value = Value.initTag(.unreachable_value),
|
||||
overflow_bit: Value,
|
||||
} = result: {
|
||||
switch (zir_tag) {
|
||||
.add_with_overflow => {
|
||||
@ -13825,24 +13833,22 @@ fn zirOverflowArithmetic(
|
||||
// Otherwise, if either of the argument is undefined, undefined is returned.
|
||||
if (maybe_lhs_val) |lhs_val| {
|
||||
if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
|
||||
break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
|
||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = rhs };
|
||||
}
|
||||
}
|
||||
if (maybe_rhs_val) |rhs_val| {
|
||||
if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
|
||||
break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
|
||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
|
||||
}
|
||||
}
|
||||
if (maybe_lhs_val) |lhs_val| {
|
||||
if (maybe_rhs_val) |rhs_val| {
|
||||
if (lhs_val.isUndef() or rhs_val.isUndef()) {
|
||||
break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
|
||||
break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
|
||||
}
|
||||
|
||||
const result = try sema.intAddWithOverflow(lhs_val, rhs_val, dest_ty);
|
||||
const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
|
||||
const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
|
||||
break :result .{ .overflowed = overflowed, .wrapped = wrapped };
|
||||
break :result .{ .overflow_bit = result.overflow_bit, .wrapped = result.wrapped_result };
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -13851,18 +13857,16 @@ fn zirOverflowArithmetic(
|
||||
// Otherwise, if either result is undefined, both results are undefined.
|
||||
if (maybe_rhs_val) |rhs_val| {
|
||||
if (rhs_val.isUndef()) {
|
||||
break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
|
||||
break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
|
||||
} else if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||
break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
|
||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
|
||||
} else if (maybe_lhs_val) |lhs_val| {
|
||||
if (lhs_val.isUndef()) {
|
||||
break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
|
||||
break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
|
||||
}
|
||||
|
||||
const result = try sema.intSubWithOverflow(lhs_val, rhs_val, dest_ty);
|
||||
const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
|
||||
const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
|
||||
break :result .{ .overflowed = overflowed, .wrapped = wrapped };
|
||||
break :result .{ .overflow_bit = result.overflow_bit, .wrapped = result.wrapped_result };
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -13873,9 +13877,9 @@ fn zirOverflowArithmetic(
|
||||
if (maybe_lhs_val) |lhs_val| {
|
||||
if (!lhs_val.isUndef()) {
|
||||
if (try lhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||
break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
|
||||
} else if (try sema.compareAll(lhs_val, .eq, Value.one, dest_ty)) {
|
||||
break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
|
||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
|
||||
} else if (try sema.compareAll(lhs_val, .eq, try maybeRepeated(sema, dest_ty, Value.one), dest_ty)) {
|
||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = rhs };
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13883,9 +13887,9 @@ fn zirOverflowArithmetic(
|
||||
if (maybe_rhs_val) |rhs_val| {
|
||||
if (!rhs_val.isUndef()) {
|
||||
if (try rhs_val.compareAllWithZeroAdvanced(.eq, sema)) {
|
||||
break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = rhs };
|
||||
} else if (try sema.compareAll(rhs_val, .eq, Value.one, dest_ty)) {
|
||||
break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
|
||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = rhs };
|
||||
} else if (try sema.compareAll(rhs_val, .eq, try maybeRepeated(sema, dest_ty, Value.one), dest_ty)) {
|
||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13893,13 +13897,11 @@ fn zirOverflowArithmetic(
|
||||
if (maybe_lhs_val) |lhs_val| {
|
||||
if (maybe_rhs_val) |rhs_val| {
|
||||
if (lhs_val.isUndef() or rhs_val.isUndef()) {
|
||||
break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
|
||||
break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
|
||||
}
|
||||
|
||||
const result = try lhs_val.intMulWithOverflow(rhs_val, dest_ty, sema.arena, mod);
|
||||
const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
|
||||
const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
|
||||
break :result .{ .overflowed = overflowed, .wrapped = wrapped };
|
||||
break :result .{ .overflow_bit = result.overflow_bit, .wrapped = result.wrapped_result };
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -13909,24 +13911,22 @@ fn zirOverflowArithmetic(
|
||||
// Oterhwise if either of the arguments is undefined, both results are undefined.
|
||||
if (maybe_lhs_val) |lhs_val| {
|
||||
if (!lhs_val.isUndef() and (try lhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
|
||||
break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
|
||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
|
||||
}
|
||||
}
|
||||
if (maybe_rhs_val) |rhs_val| {
|
||||
if (!rhs_val.isUndef() and (try rhs_val.compareAllWithZeroAdvanced(.eq, sema))) {
|
||||
break :result .{ .overflowed = try sema.addBool(overflowed_ty, false), .wrapped = lhs };
|
||||
break :result .{ .overflow_bit = try maybeRepeated(sema, dest_ty, Value.zero), .inst = lhs };
|
||||
}
|
||||
}
|
||||
if (maybe_lhs_val) |lhs_val| {
|
||||
if (maybe_rhs_val) |rhs_val| {
|
||||
if (lhs_val.isUndef() or rhs_val.isUndef()) {
|
||||
break :result .{ .overflowed = try sema.addConstUndef(overflowed_ty), .wrapped = try sema.addConstUndef(dest_ty) };
|
||||
break :result .{ .overflow_bit = Value.undef, .wrapped = Value.undef };
|
||||
}
|
||||
|
||||
const result = try lhs_val.shlWithOverflow(rhs_val, dest_ty, sema.arena, sema.mod);
|
||||
const overflowed = try sema.addConstant(overflowed_ty, result.overflowed);
|
||||
const wrapped = try sema.addConstant(dest_ty, result.wrapped_result);
|
||||
break :result .{ .overflowed = overflowed, .wrapped = wrapped };
|
||||
break :result .{ .overflow_bit = result.overflow_bit, .wrapped = result.wrapped_result };
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -13944,7 +13944,7 @@ fn zirOverflowArithmetic(
|
||||
const runtime_src = if (maybe_lhs_val == null) lhs_src else rhs_src;
|
||||
try sema.requireRuntimeBlock(block, src, runtime_src);
|
||||
|
||||
const tuple = try block.addInst(.{
|
||||
return block.addInst(.{
|
||||
.tag = air_tag,
|
||||
.data = .{ .ty_pl = .{
|
||||
.ty = try block.sema.addType(tuple_ty),
|
||||
@ -13954,16 +13954,32 @@ fn zirOverflowArithmetic(
|
||||
}),
|
||||
} },
|
||||
});
|
||||
|
||||
const wrapped = try sema.tupleFieldValByIndex(block, src, tuple, 0, tuple_ty);
|
||||
try sema.storePtr2(block, src, ptr, ptr_src, wrapped, src, .store);
|
||||
|
||||
const overflow_bit = try sema.tupleFieldValByIndex(block, src, tuple, 1, tuple_ty);
|
||||
return block.addBitCast(overflowed_ty, overflow_bit);
|
||||
};
|
||||
|
||||
try sema.storePtr2(block, src, ptr, ptr_src, result.wrapped, src, .store);
|
||||
return result.overflowed;
|
||||
if (result.inst != .none) {
|
||||
if (try sema.resolveMaybeUndefVal(result.inst)) |some| {
|
||||
result.wrapped = some;
|
||||
result.inst = .none;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.inst == .none) {
|
||||
const values = try sema.arena.alloc(Value, 2);
|
||||
values[0] = result.wrapped;
|
||||
values[1] = result.overflow_bit;
|
||||
const tuple_val = try Value.Tag.aggregate.create(sema.arena, values);
|
||||
return sema.addConstant(tuple_ty, tuple_val);
|
||||
}
|
||||
|
||||
const element_refs = try sema.arena.alloc(Air.Inst.Ref, 2);
|
||||
element_refs[0] = result.inst;
|
||||
element_refs[1] = try sema.addConstant(tuple_ty.structFieldType(1), result.overflow_bit);
|
||||
return block.addAggregateInit(tuple_ty, element_refs);
|
||||
}
|
||||
|
||||
fn maybeRepeated(sema: *Sema, ty: Type, val: Value) !Value {
|
||||
if (ty.zigTypeTag() != .Vector) return val;
|
||||
return Value.Tag.repeated.create(sema.arena, val);
|
||||
}
|
||||
|
||||
fn overflowArithmeticTupleType(sema: *Sema, ty: Type) !Type {
|
||||
@ -16211,14 +16227,6 @@ fn zirTypeofLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
|
||||
return sema.addType(res_ty);
|
||||
}
|
||||
|
||||
fn zirLog2IntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||
const src = inst_data.src();
|
||||
const operand = try sema.resolveType(block, src, inst_data.operand);
|
||||
const res_ty = try sema.log2IntType(block, operand, src);
|
||||
return sema.addType(res_ty);
|
||||
}
|
||||
|
||||
fn log2IntType(sema: *Sema, block: *Block, operand: Type, src: LazySrcLoc) CompileError!Type {
|
||||
switch (operand.zigTypeTag()) {
|
||||
.ComptimeInt => return Type.comptime_int,
|
||||
@ -17039,24 +17047,6 @@ fn floatOpAllowed(tag: Zir.Inst.Tag) bool {
|
||||
};
|
||||
}
|
||||
|
||||
fn zirOverflowArithmeticPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||
const elem_ty_src = inst_data.src();
|
||||
const elem_type = try sema.resolveType(block, elem_ty_src, inst_data.operand);
|
||||
const ty = try Type.ptr(sema.arena, sema.mod, .{
|
||||
.pointee_type = elem_type,
|
||||
.@"addrspace" = .generic,
|
||||
.mutable = true,
|
||||
.@"allowzero" = false,
|
||||
.@"volatile" = false,
|
||||
.size = .One,
|
||||
});
|
||||
return sema.addType(ty);
|
||||
}
|
||||
|
||||
fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
@ -32613,11 +32603,11 @@ fn intSubWithOverflow(
|
||||
const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
|
||||
const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
|
||||
const of_math_result = try sema.intSubWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType());
|
||||
overflowed_data[i] = of_math_result.overflowed;
|
||||
overflowed_data[i] = of_math_result.overflow_bit;
|
||||
scalar.* = of_math_result.wrapped_result;
|
||||
}
|
||||
return Value.OverflowArithmeticResult{
|
||||
.overflowed = try Value.Tag.aggregate.create(sema.arena, overflowed_data),
|
||||
.overflow_bit = try Value.Tag.aggregate.create(sema.arena, overflowed_data),
|
||||
.wrapped_result = try Value.Tag.aggregate.create(sema.arena, result_data),
|
||||
};
|
||||
}
|
||||
@ -32645,7 +32635,7 @@ fn intSubWithOverflowScalar(
|
||||
const overflowed = result_bigint.subWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
|
||||
const wrapped_result = try Value.fromBigInt(sema.arena, result_bigint.toConst());
|
||||
return Value.OverflowArithmeticResult{
|
||||
.overflowed = Value.makeBool(overflowed),
|
||||
.overflow_bit = Value.boolToInt(overflowed),
|
||||
.wrapped_result = wrapped_result,
|
||||
};
|
||||
}
|
||||
@ -32964,11 +32954,11 @@ fn intAddWithOverflow(
|
||||
const lhs_elem = lhs.elemValueBuffer(sema.mod, i, &lhs_buf);
|
||||
const rhs_elem = rhs.elemValueBuffer(sema.mod, i, &rhs_buf);
|
||||
const of_math_result = try sema.intAddWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType());
|
||||
overflowed_data[i] = of_math_result.overflowed;
|
||||
overflowed_data[i] = of_math_result.overflow_bit;
|
||||
scalar.* = of_math_result.wrapped_result;
|
||||
}
|
||||
return Value.OverflowArithmeticResult{
|
||||
.overflowed = try Value.Tag.aggregate.create(sema.arena, overflowed_data),
|
||||
.overflow_bit = try Value.Tag.aggregate.create(sema.arena, overflowed_data),
|
||||
.wrapped_result = try Value.Tag.aggregate.create(sema.arena, result_data),
|
||||
};
|
||||
}
|
||||
@ -32996,7 +32986,7 @@ fn intAddWithOverflowScalar(
|
||||
const overflowed = result_bigint.addWrap(lhs_bigint, rhs_bigint, info.signedness, info.bits);
|
||||
const result = try Value.fromBigInt(sema.arena, result_bigint.toConst());
|
||||
return Value.OverflowArithmeticResult{
|
||||
.overflowed = Value.makeBool(overflowed),
|
||||
.overflow_bit = Value.boolToInt(overflowed),
|
||||
.wrapped_result = result,
|
||||
};
|
||||
}
|
||||
|
||||
@ -225,9 +225,7 @@ pub fn print(
|
||||
.one => return writer.writeAll("1"),
|
||||
.void_value => return writer.writeAll("{}"),
|
||||
.unreachable_value => return writer.writeAll("unreachable"),
|
||||
.the_only_possible_value => {
|
||||
val = ty.onePossibleValue().?;
|
||||
},
|
||||
.the_only_possible_value => return writer.writeAll("0"),
|
||||
.bool_true => return writer.writeAll("true"),
|
||||
.bool_false => return writer.writeAll("false"),
|
||||
.ty => return val.castTag(.ty).?.data.print(writer, mod),
|
||||
|
||||
27
src/Zir.zig
27
src/Zir.zig
@ -539,9 +539,6 @@ pub const Inst = struct {
|
||||
/// Obtains the return type of the in-scope function.
|
||||
/// Uses the `node` union field.
|
||||
ret_type,
|
||||
/// Create a pointer type for overflow arithmetic.
|
||||
/// TODO remove when doing https://github.com/ziglang/zig/issues/10248
|
||||
overflow_arithmetic_ptr,
|
||||
/// Create a pointer type which can have a sentinel, alignment, address space, and/or bit range.
|
||||
/// Uses the `ptr_type` union field.
|
||||
ptr_type,
|
||||
@ -600,9 +597,6 @@ pub const Inst = struct {
|
||||
/// Returns the integer type for the RHS of a shift operation.
|
||||
/// Uses the `un_node` field.
|
||||
typeof_log2_int_type,
|
||||
/// Given an integer type, returns the integer type for the RHS of a shift operation.
|
||||
/// Uses the `un_node` field.
|
||||
log2_int_type,
|
||||
/// Asserts control-flow will not reach this instruction (`unreachable`).
|
||||
/// Uses the `unreachable` union field.
|
||||
@"unreachable",
|
||||
@ -1121,7 +1115,6 @@ pub const Inst = struct {
|
||||
.err_union_code,
|
||||
.err_union_code_ptr,
|
||||
.ptr_type,
|
||||
.overflow_arithmetic_ptr,
|
||||
.enum_literal,
|
||||
.merge_error_sets,
|
||||
.error_union_type,
|
||||
@ -1132,7 +1125,6 @@ pub const Inst = struct {
|
||||
.slice_sentinel,
|
||||
.import,
|
||||
.typeof_log2_int_type,
|
||||
.log2_int_type,
|
||||
.resolve_inferred_alloc,
|
||||
.set_eval_branch_quota,
|
||||
.switch_capture,
|
||||
@ -1422,7 +1414,6 @@ pub const Inst = struct {
|
||||
.err_union_code,
|
||||
.err_union_code_ptr,
|
||||
.ptr_type,
|
||||
.overflow_arithmetic_ptr,
|
||||
.enum_literal,
|
||||
.merge_error_sets,
|
||||
.error_union_type,
|
||||
@ -1433,7 +1424,6 @@ pub const Inst = struct {
|
||||
.slice_sentinel,
|
||||
.import,
|
||||
.typeof_log2_int_type,
|
||||
.log2_int_type,
|
||||
.switch_capture,
|
||||
.switch_capture_ref,
|
||||
.switch_capture_multi,
|
||||
@ -1664,7 +1654,6 @@ pub const Inst = struct {
|
||||
.ret_err_value_code = .str_tok,
|
||||
.ret_ptr = .node,
|
||||
.ret_type = .node,
|
||||
.overflow_arithmetic_ptr = .un_node,
|
||||
.ptr_type = .ptr_type,
|
||||
.slice_start = .pl_node,
|
||||
.slice_end = .pl_node,
|
||||
@ -1678,7 +1667,6 @@ pub const Inst = struct {
|
||||
.negate_wrap = .un_node,
|
||||
.typeof = .un_node,
|
||||
.typeof_log2_int_type = .un_node,
|
||||
.log2_int_type = .un_node,
|
||||
.@"unreachable" = .@"unreachable",
|
||||
.xor = .pl_node,
|
||||
.optional_type = .un_node,
|
||||
@ -1916,19 +1904,19 @@ pub const Inst = struct {
|
||||
/// The AST node is the builtin call.
|
||||
typeof_peer,
|
||||
/// Implements the `@addWithOverflow` builtin.
|
||||
/// `operand` is payload index to `OverflowArithmetic`.
|
||||
/// `operand` is payload index to `BinNode`.
|
||||
/// `small` is unused.
|
||||
add_with_overflow,
|
||||
/// Implements the `@subWithOverflow` builtin.
|
||||
/// `operand` is payload index to `OverflowArithmetic`.
|
||||
/// `operand` is payload index to `BinNode`.
|
||||
/// `small` is unused.
|
||||
sub_with_overflow,
|
||||
/// Implements the `@mulWithOverflow` builtin.
|
||||
/// `operand` is payload index to `OverflowArithmetic`.
|
||||
/// `operand` is payload index to `BinNode`.
|
||||
/// `small` is unused.
|
||||
mul_with_overflow,
|
||||
/// Implements the `@shlWithOverflow` builtin.
|
||||
/// `operand` is payload index to `OverflowArithmetic`.
|
||||
/// `operand` is payload index to `BinNode`.
|
||||
/// `small` is unused.
|
||||
shl_with_overflow,
|
||||
/// `operand` is payload index to `UnNode`.
|
||||
@ -3430,13 +3418,6 @@ pub const Inst = struct {
|
||||
field_name: Ref,
|
||||
};
|
||||
|
||||
pub const OverflowArithmetic = struct {
|
||||
node: i32,
|
||||
lhs: Ref,
|
||||
rhs: Ref,
|
||||
ptr: Ref,
|
||||
};
|
||||
|
||||
pub const Cmpxchg = struct {
|
||||
node: i32,
|
||||
ptr: Ref,
|
||||
|
||||
@ -185,7 +185,6 @@ const Writer = struct {
|
||||
.size_of,
|
||||
.bit_size_of,
|
||||
.typeof_log2_int_type,
|
||||
.log2_int_type,
|
||||
.ptr_to_int,
|
||||
.compile_error,
|
||||
.set_eval_branch_quota,
|
||||
@ -230,7 +229,6 @@ const Writer = struct {
|
||||
.validate_struct_init_ty,
|
||||
.make_ptr_const,
|
||||
.validate_deref,
|
||||
.overflow_arithmetic_ptr,
|
||||
.check_comptime_control_flow,
|
||||
=> try self.writeUnNode(stream, inst),
|
||||
|
||||
@ -1153,14 +1151,12 @@ const Writer = struct {
|
||||
}
|
||||
|
||||
fn writeOverflowArithmetic(self: *Writer, stream: anytype, extended: Zir.Inst.Extended.InstData) !void {
|
||||
const extra = self.code.extraData(Zir.Inst.OverflowArithmetic, extended.operand).data;
|
||||
const extra = self.code.extraData(Zir.Inst.BinNode, extended.operand).data;
|
||||
const src = LazySrcLoc.nodeOffset(extra.node);
|
||||
|
||||
try self.writeInstRef(stream, extra.lhs);
|
||||
try stream.writeAll(", ");
|
||||
try self.writeInstRef(stream, extra.rhs);
|
||||
try stream.writeAll(", ");
|
||||
try self.writeInstRef(stream, extra.ptr);
|
||||
try stream.writeAll(")) ");
|
||||
try self.writeSrc(stream, src);
|
||||
}
|
||||
|
||||
@ -3123,6 +3123,7 @@ pub const Type = extern union {
|
||||
for (tuple.types) |field_ty, i| {
|
||||
const val = tuple.values[i];
|
||||
if (val.tag() != .unreachable_value) continue; // comptime field
|
||||
if (!(field_ty.hasRuntimeBits())) continue;
|
||||
|
||||
switch (try field_ty.abiAlignmentAdvanced(target, strat)) {
|
||||
.scalar => |field_align| big_align = @max(big_align, field_align),
|
||||
|
||||
@ -3259,8 +3259,7 @@ pub const Value = extern union {
|
||||
}
|
||||
|
||||
pub const OverflowArithmeticResult = struct {
|
||||
/// TODO: Rename to `overflow_bit` and make of type `u1`.
|
||||
overflowed: Value,
|
||||
overflow_bit: Value,
|
||||
wrapped_result: Value,
|
||||
};
|
||||
|
||||
@ -3395,11 +3394,11 @@ pub const Value = extern union {
|
||||
const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
|
||||
const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
|
||||
const of_math_result = try intMulWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType(), arena, target);
|
||||
overflowed_data[i] = of_math_result.overflowed;
|
||||
overflowed_data[i] = of_math_result.overflow_bit;
|
||||
scalar.* = of_math_result.wrapped_result;
|
||||
}
|
||||
return OverflowArithmeticResult{
|
||||
.overflowed = try Value.Tag.aggregate.create(arena, overflowed_data),
|
||||
.overflow_bit = try Value.Tag.aggregate.create(arena, overflowed_data),
|
||||
.wrapped_result = try Value.Tag.aggregate.create(arena, result_data),
|
||||
};
|
||||
}
|
||||
@ -3436,7 +3435,7 @@ pub const Value = extern union {
|
||||
}
|
||||
|
||||
return OverflowArithmeticResult{
|
||||
.overflowed = makeBool(overflowed),
|
||||
.overflow_bit = boolToInt(overflowed),
|
||||
.wrapped_result = try fromBigInt(arena, result_bigint.toConst()),
|
||||
};
|
||||
}
|
||||
@ -4141,11 +4140,11 @@ pub const Value = extern union {
|
||||
const lhs_elem = lhs.elemValueBuffer(mod, i, &lhs_buf);
|
||||
const rhs_elem = rhs.elemValueBuffer(mod, i, &rhs_buf);
|
||||
const of_math_result = try shlWithOverflowScalar(lhs_elem, rhs_elem, ty.scalarType(), allocator, target);
|
||||
overflowed_data[i] = of_math_result.overflowed;
|
||||
overflowed_data[i] = of_math_result.overflow_bit;
|
||||
scalar.* = of_math_result.wrapped_result;
|
||||
}
|
||||
return OverflowArithmeticResult{
|
||||
.overflowed = try Value.Tag.aggregate.create(allocator, overflowed_data),
|
||||
.overflow_bit = try Value.Tag.aggregate.create(allocator, overflowed_data),
|
||||
.wrapped_result = try Value.Tag.aggregate.create(allocator, result_data),
|
||||
};
|
||||
}
|
||||
@ -4178,7 +4177,7 @@ pub const Value = extern union {
|
||||
result_bigint.truncate(result_bigint.toConst(), info.signedness, info.bits);
|
||||
}
|
||||
return OverflowArithmeticResult{
|
||||
.overflowed = makeBool(overflowed),
|
||||
.overflow_bit = boolToInt(overflowed),
|
||||
.wrapped_result = try fromBigInt(allocator, result_bigint.toConst()),
|
||||
};
|
||||
}
|
||||
@ -5492,6 +5491,10 @@ pub const Value = extern union {
|
||||
return if (x) Value.true else Value.false;
|
||||
}
|
||||
|
||||
pub fn boolToInt(x: bool) Value {
|
||||
return if (x) Value.one else Value.zero;
|
||||
}
|
||||
|
||||
pub const RuntimeIndex = enum(u32) {
|
||||
zero = 0,
|
||||
comptime_field_ptr = std.math.maxInt(u32),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user