mirror of
https://github.com/ziglang/zig.git
synced 2026-01-26 01:05:22 +00:00
stage2: bitNot
This commit is contained in:
parent
6a3659c4e0
commit
9336a87452
38
src/Sema.zig
38
src/Sema.zig
@ -6627,8 +6627,42 @@ fn zirBitNot(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.
|
||||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
_ = inst;
|
||||
return sema.fail(block, sema.src, "TODO implement zirBitNot", .{});
|
||||
const inst_data = sema.code.instructions.items(.data)[inst].un_node;
|
||||
const src = inst_data.src();
|
||||
const operand_src = src; // TODO put this on the operand, not the '~'
|
||||
|
||||
const operand = sema.resolveInst(inst_data.operand);
|
||||
const operand_type = sema.typeOf(operand);
|
||||
const scalar_type = operand_type.scalarType();
|
||||
|
||||
if (scalar_type.zigTypeTag() != .Int) {
|
||||
return sema.fail(block, src, "unable to perform binary not operation on type '{}'", .{operand_type});
|
||||
}
|
||||
|
||||
if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
|
||||
const target = sema.mod.getTarget();
|
||||
if (val.isUndef()) {
|
||||
return sema.addConstUndef(scalar_type);
|
||||
} else if (operand_type.zigTypeTag() == .Vector) {
|
||||
const vec_len = operand_type.arrayLen();
|
||||
var elem_val_buf: Value.ElemValueBuffer = undefined;
|
||||
const elems = try sema.arena.alloc(Value, vec_len);
|
||||
for (elems) |*elem, i| {
|
||||
const elem_val = val.elemValueBuffer(i, &elem_val_buf);
|
||||
elem.* = try elem_val.bitwiseNot(scalar_type, sema.arena, target);
|
||||
}
|
||||
return sema.addConstant(
|
||||
operand_type,
|
||||
try Value.Tag.array.create(sema.arena, elems),
|
||||
);
|
||||
} else {
|
||||
const result_val = try val.bitwiseNot(scalar_type, sema.arena, target);
|
||||
return sema.addConstant(scalar_type, result_val);
|
||||
}
|
||||
}
|
||||
|
||||
try sema.requireRuntimeBlock(block, src);
|
||||
return block.addTyOp(.not, operand_type, operand);
|
||||
}
|
||||
|
||||
fn zirArrayCat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
|
||||
@ -2081,6 +2081,32 @@ pub const Value = extern union {
|
||||
};
|
||||
}
|
||||
|
||||
/// operands must be integers; handles undefined.
|
||||
pub fn bitwiseNot(val: Value, ty: Type, arena: *Allocator, target: Target) !Value {
|
||||
if (val.isUndef()) return Value.initTag(.undef);
|
||||
|
||||
const info = ty.intInfo(target);
|
||||
|
||||
// TODO is this a performance issue? maybe we should try the operation without
|
||||
// resorting to BigInt first.
|
||||
var val_space: Value.BigIntSpace = undefined;
|
||||
const val_bigint = val.toBigInt(&val_space);
|
||||
const limbs = try arena.alloc(
|
||||
std.math.big.Limb,
|
||||
std.math.big.int.calcTwosCompLimbCount(info.bits),
|
||||
);
|
||||
|
||||
var result_bigint = BigIntMutable{ .limbs = limbs, .positive = undefined, .len = undefined };
|
||||
result_bigint.bitNotWrap(val_bigint, info.signedness, info.bits);
|
||||
const result_limbs = result_bigint.limbs[0..result_bigint.len];
|
||||
|
||||
if (result_bigint.positive) {
|
||||
return Value.Tag.int_big_positive.create(arena, result_limbs);
|
||||
} else {
|
||||
return Value.Tag.int_big_negative.create(arena, result_limbs);
|
||||
}
|
||||
}
|
||||
|
||||
/// operands must be integers; handles undefined.
|
||||
pub fn bitwiseAnd(lhs: Value, rhs: Value, arena: *Allocator) !Value {
|
||||
if (lhs.isUndef() or rhs.isUndef()) return Value.initTag(.undef);
|
||||
|
||||
@ -235,3 +235,17 @@ test "comptime_int param and return" {
|
||||
fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
test "binary not" {
|
||||
try expect(comptime x: {
|
||||
break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101;
|
||||
});
|
||||
try expect(comptime x: {
|
||||
break :x ~@as(u64, 2147483647) == 18446744071562067968;
|
||||
});
|
||||
try testBinaryNot(0b1010101010101010);
|
||||
}
|
||||
|
||||
fn testBinaryNot(x: u16) !void {
|
||||
try expect(~x == 0b0101010101010101);
|
||||
}
|
||||
|
||||
@ -219,20 +219,6 @@ const DivResult = struct {
|
||||
remainder: u64,
|
||||
};
|
||||
|
||||
test "binary not" {
|
||||
try expect(comptime x: {
|
||||
break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101;
|
||||
});
|
||||
try expect(comptime x: {
|
||||
break :x ~@as(u64, 2147483647) == 18446744071562067968;
|
||||
});
|
||||
try testBinaryNot(0b1010101010101010);
|
||||
}
|
||||
|
||||
fn testBinaryNot(x: u16) !void {
|
||||
try expect(~x == 0b0101010101010101);
|
||||
}
|
||||
|
||||
test "small int addition" {
|
||||
var x: u2 = 0;
|
||||
try expect(x == 0);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user