authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-31 02:23:39-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-31 02:23:39-05:00
log5f89393acb0e3626d942302ca24de14349850040
tree4392876029f534373236086987e61fafcf545b49
parent2ccdaee101e6e0d8cb4a4560b032ff9bab4b5f58

IR: implement binary not instruction


4 files changed, 46 insertions(+), 15 deletions(-)

src/bignum.cpp+7
......@@ -142,6 +142,13 @@ void bignum_negate(BigNum *dest, BigNum *op) {
142142 }
143143}
144144
145void bignum_not(BigNum *dest, BigNum *op, int bit_count) {
146 assert(op->kind == BigNumKindInt);
147 uint64_t bits = ~bignum_to_twos_complement(op);
148 bits &= (1LL << bit_count) - 1;
149 bignum_init_signed(dest, bits);
150}
151
145152void bignum_cast_to_float(BigNum *dest, BigNum *op) {
146153 assert(op->kind == BigNumKindInt);
147154 dest->kind = BigNumKindFloat;
src/bignum.hpp+1
......@@ -48,6 +48,7 @@ bool bignum_shr(BigNum *dest, BigNum *op1, BigNum *op2);
4848void bignum_negate(BigNum *dest, BigNum *op);
4949void bignum_cast_to_float(BigNum *dest, BigNum *op);
5050void bignum_cast_to_int(BigNum *dest, BigNum *op);
51void bignum_not(BigNum *dest, BigNum *op, int bit_count);
5152
5253void bignum_truncate(BigNum *dest, int bit_count);
5354
src/ir.cpp+28-15
......@@ -7811,27 +7811,40 @@ static TypeTableEntry *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *un
78117811 return ira->codegen->builtin_types.entry_invalid;
78127812}
78137813
7814static TypeTableEntry *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *instruction) {
7815 IrInstruction *value = instruction->value->other;
7816 TypeTableEntry *expr_type = value->value.type;
7817 if (expr_type->id == TypeTableEntryIdInvalid)
7818 return ira->codegen->builtin_types.entry_invalid;
7819
7820 if (expr_type->id == TypeTableEntryIdInt) {
7821 if (instr_is_comptime(value)) {
7822 ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad);
7823 if (!target_const_val)
7824 return ira->codegen->builtin_types.entry_invalid;
7825
7826 bool depends_on_compile_var = value->value.depends_on_compile_var;
7827 ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
7828 bignum_not(&out_val->data.x_bignum, &target_const_val->data.x_bignum, expr_type->data.integral.bit_count);
7829 return expr_type;
7830 }
7831
7832 ir_build_un_op_from(&ira->new_irb, &instruction->base, IrUnOpBinNot, value);
7833 return expr_type;
7834 }
7835
7836 ir_add_error(ira, &instruction->base,
7837 buf_sprintf("unable to perform binary not operation on type '%s'", buf_ptr(&expr_type->name)));
7838 return ira->codegen->builtin_types.entry_invalid;
7839}
7840
78147841static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
78157842 IrUnOp op_id = un_op_instruction->op_id;
78167843 switch (op_id) {
78177844 case IrUnOpInvalid:
78187845 zig_unreachable();
78197846 case IrUnOpBinNot:
7820 zig_panic("TODO analyze PrefixOpBinNot");
7821 //{
7822 // TypeTableEntry *expr_type = analyze_expression(g, import, context, expected_type,
7823 // *expr_node);
7824 // if (expr_type->id == TypeTableEntryIdInvalid) {
7825 // return expr_type;
7826 // } else if (expr_type->id == TypeTableEntryIdInt) {
7827 // return expr_type;
7828 // } else {
7829 // add_node_error(g, node, buf_sprintf("unable to perform binary not operation on type '%s'",
7830 // buf_ptr(&expr_type->name)));
7831 // return g->builtin_types.entry_invalid;
7832 // }
7833 // // TODO const expr eval
7834 //}
7847 return ir_analyze_bin_not(ira, un_op_instruction);
78357848 case IrUnOpNegation:
78367849 case IrUnOpNegationWrap:
78377850 return ir_analyze_negation(ira, un_op_instruction);
test/cases/math.zig+10
......@@ -164,6 +164,16 @@ const DivResult = struct {
164164 remainder: u64,
165165};
166166
167fn binaryNot() {
168 @setFnTest(this);
169
170 assert(~u16(0b1010101010101010) == 0b0101010101010101);
171 testBinaryNot(0b1010101010101010);
172}
173
174fn testBinaryNot(x: u16) {
175 assert(~x == 0b0101010101010101);
176}
167177
168178// TODO const assert = @import("std").debug.assert;
169179fn assert(ok: bool) {