mirror of
https://github.com/ziglang/zig.git
synced 2024-12-03 10:28:48 +00:00
IR: implement binary not instruction
This commit is contained in:
parent
2ccdaee101
commit
5f89393acb
@ -142,6 +142,13 @@ void bignum_negate(BigNum *dest, BigNum *op) {
|
||||
}
|
||||
}
|
||||
|
||||
void bignum_not(BigNum *dest, BigNum *op, int bit_count) {
|
||||
assert(op->kind == BigNumKindInt);
|
||||
uint64_t bits = ~bignum_to_twos_complement(op);
|
||||
bits &= (1LL << bit_count) - 1;
|
||||
bignum_init_signed(dest, bits);
|
||||
}
|
||||
|
||||
void bignum_cast_to_float(BigNum *dest, BigNum *op) {
|
||||
assert(op->kind == BigNumKindInt);
|
||||
dest->kind = BigNumKindFloat;
|
||||
|
@ -48,6 +48,7 @@ bool bignum_shr(BigNum *dest, BigNum *op1, BigNum *op2);
|
||||
void bignum_negate(BigNum *dest, BigNum *op);
|
||||
void bignum_cast_to_float(BigNum *dest, BigNum *op);
|
||||
void bignum_cast_to_int(BigNum *dest, BigNum *op);
|
||||
void bignum_not(BigNum *dest, BigNum *op, int bit_count);
|
||||
|
||||
void bignum_truncate(BigNum *dest, int bit_count);
|
||||
|
||||
|
43
src/ir.cpp
43
src/ir.cpp
@ -7811,27 +7811,40 @@ static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *instruction) {
|
||||
IrInstruction *value = instruction->value->other;
|
||||
TypeTableEntry *expr_type = value->value.type;
|
||||
if (expr_type->id == TypeTableEntryIdInvalid)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
if (expr_type->id == TypeTableEntryIdInt) {
|
||||
if (instr_is_comptime(value)) {
|
||||
ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad);
|
||||
if (!target_const_val)
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
|
||||
bool depends_on_compile_var = value->value.depends_on_compile_var;
|
||||
ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
|
||||
bignum_not(&out_val->data.x_bignum, &target_const_val->data.x_bignum, expr_type->data.integral.bit_count);
|
||||
return expr_type;
|
||||
}
|
||||
|
||||
ir_build_un_op_from(&ira->new_irb, &instruction->base, IrUnOpBinNot, value);
|
||||
return expr_type;
|
||||
}
|
||||
|
||||
ir_add_error(ira, &instruction->base,
|
||||
buf_sprintf("unable to perform binary not operation on type '%s'", buf_ptr(&expr_type->name)));
|
||||
return ira->codegen->builtin_types.entry_invalid;
|
||||
}
|
||||
|
||||
static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
|
||||
IrUnOp op_id = un_op_instruction->op_id;
|
||||
switch (op_id) {
|
||||
case IrUnOpInvalid:
|
||||
zig_unreachable();
|
||||
case IrUnOpBinNot:
|
||||
zig_panic("TODO analyze PrefixOpBinNot");
|
||||
//{
|
||||
// TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
|
||||
// *expr_node);
|
||||
// if (expr_type->id == TypeTableEntryIdInvalid) {
|
||||
// return expr_type;
|
||||
// } else if (expr_type->id == TypeTableEntryIdInt) {
|
||||
// return expr_type;
|
||||
// } else {
|
||||
// add_node_error(g, node, buf_sprintf("unable to perform binary not operation on type '%s'",
|
||||
// buf_ptr(&expr_type->name)));
|
||||
// return g->builtin_types.entry_invalid;
|
||||
// }
|
||||
// // TODO const expr eval
|
||||
//}
|
||||
return ir_analyze_bin_not(ira, un_op_instruction);
|
||||
case IrUnOpNegation:
|
||||
case IrUnOpNegationWrap:
|
||||
return ir_analyze_negation(ira, un_op_instruction);
|
||||
|
@ -164,6 +164,16 @@ const DivResult = struct {
|
||||
remainder: u64,
|
||||
};
|
||||
|
||||
fn binaryNot() {
|
||||
@setFnTest(this);
|
||||
|
||||
assert(~u16(0b1010101010101010) == 0b0101010101010101);
|
||||
testBinaryNot(0b1010101010101010);
|
||||
}
|
||||
|
||||
fn testBinaryNot(x: u16) {
|
||||
assert(~x == 0b0101010101010101);
|
||||
}
|
||||
|
||||
// TODO const assert = @import("std").debug.assert;
|
||||
fn assert(ok: bool) {
|
||||
|
Loading…
Reference in New Issue
Block a user