| author | |
| committer | |
| log | 870341e32e4fa4c8ef1bc3b0163d6530cab5911e |
| tree | 1b3a42c965a89225fbde7540a72e3412a3330002 |
| parent | f3f5a5d05b7056aceb408b701613242d053019ab |
2 files changed, 122 insertions(+), 16 deletions(-)
src/Sema.zig+46-16| ... | ... | @@ -13575,28 +13575,58 @@ fn zirByteSwap(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 13575 | 13575 | |
| 13576 | 13576 | fn zirBitReverse(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 13577 | 13577 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 13578 | const ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; | |
| 13579 | 13578 | const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; |
| 13580 | 13579 | const operand = sema.resolveInst(inst_data.operand); |
| 13581 | 13580 | const operand_ty = sema.typeOf(operand); |
| 13582 | // TODO implement support for vectors | |
| 13583 | if (operand_ty.zigTypeTag() != .Int) { | |
| 13584 | return sema.fail(block, ty_src, "expected integer type, found '{}'", .{ | |
| 13585 | operand_ty, | |
| 13586 | }); | |
| 13587 | } | |
| 13581 | const scalar_ty = try sema.checkIntOrVectorAllowComptime(block, operand, operand_src); | |
| 13582 | ||
| 13588 | 13583 | const target = sema.mod.getTarget(); |
| 13589 | const bits = operand_ty.intInfo(target).bits; | |
| 13590 | if (bits == 0) return Air.Inst.Ref.zero; | |
| 13584 | const bits = scalar_ty.intInfo(target).bits; | |
| 13585 | if (bits == 0) { | |
| 13586 | switch (operand_ty.zigTypeTag()) { | |
| 13587 | .Vector => return sema.addConstant( | |
| 13588 | operand_ty, | |
| 13589 | try Value.Tag.repeated.create(sema.arena, Value.zero), | |
| 13590 | ), | |
| 13591 | .Int => return Air.Inst.Ref.zero, | |
| 13592 | else => unreachable, | |
| 13593 | } | |
| 13594 | } | |
| 13591 | 13595 | |
| 13592 | const runtime_src = if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { | |
| 13593 | if (val.isUndef()) return sema.addConstUndef(operand_ty); | |
| 13594 | const result_val = try val.bitReverse(operand_ty, target, sema.arena); | |
| 13595 | return sema.addConstant(operand_ty, result_val); | |
| 13596 | } else operand_src; | |
| 13596 | switch (operand_ty.zigTypeTag()) { | |
| 13597 | .Int, .ComptimeInt => { | |
| 13598 | const runtime_src = if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { | |
| 13599 | if (val.isUndef()) return sema.addConstUndef(operand_ty); | |
| 13600 | const result_val = try val.bitReverse(operand_ty, target, sema.arena); | |
| 13601 | return sema.addConstant(operand_ty, result_val); | |
| 13602 | } else operand_src; | |
| 13597 | 13603 | |
| 13598 | try sema.requireRuntimeBlock(block, runtime_src); | |
| 13599 | return block.addTyOp(.bit_reverse, operand_ty, operand); | |
| 13604 | try sema.requireRuntimeBlock(block, runtime_src); | |
| 13605 | return block.addTyOp(.bit_reverse, operand_ty, operand); | |
| 13606 | }, | |
| 13607 | .Vector => { | |
| 13608 | const runtime_src = if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| { | |
| 13609 | if (val.isUndef()) | |
| 13610 | return sema.addConstUndef(operand_ty); | |
| 13611 | ||
| 13612 | const vec_len = operand_ty.vectorLen(); | |
| 13613 | var elem_buf: Value.ElemValueBuffer = undefined; | |
| 13614 | const elems = try sema.arena.alloc(Value, vec_len); | |
| 13615 | for (elems) |*elem, i| { | |
| 13616 | const elem_val = val.elemValueBuffer(i, &elem_buf); | |
| 13617 | elem.* = try elem_val.bitReverse(operand_ty, target, sema.arena); | |
| 13618 | } | |
| 13619 | return sema.addConstant( | |
| 13620 | operand_ty, | |
| 13621 | try Value.Tag.aggregate.create(sema.arena, elems), | |
| 13622 | ); | |
| 13623 | } else operand_src; | |
| 13624 | ||
| 13625 | try sema.requireRuntimeBlock(block, runtime_src); | |
| 13626 | return block.addTyOp(.bit_reverse, operand_ty, operand); | |
| 13627 | }, | |
| 13628 | else => unreachable, | |
| 13629 | } | |
| 13600 | 13630 | } |
| 13601 | 13631 | |
| 13602 | 13632 | fn zirBitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
test/behavior/bitreverse.zig+76| ... | ... | @@ -87,3 +87,79 @@ fn testBitReverse() !void { |
| 87 | 87 | var neg32: i32 = -16773785; |
| 88 | 88 | try expect(@bitReverse(i32, @as(i32, -16773785)) == @bitReverse(i32, neg32)); |
| 89 | 89 | } |
| 90 | ||
| 91 | fn vector8() !void { | |
| 92 | var v = @Vector(2, u8){ 0x12, 0x23 }; | |
| 93 | var result = @bitReverse(u8, v); | |
| 94 | try expect(result[0] == 0x48); | |
| 95 | try expect(result[1] == 0xc4); | |
| 96 | } | |
| 97 | ||
| 98 | test "bitReverse vectors u8" { | |
| 99 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | |
| 100 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 101 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 102 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 103 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 104 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 105 | ||
| 106 | comptime try vector8(); | |
| 107 | try vector8(); | |
| 108 | } | |
| 109 | ||
| 110 | fn vector16() !void { | |
| 111 | var v = @Vector(2, u16){ 0x1234, 0x2345 }; | |
| 112 | var result = @bitReverse(u16, v); | |
| 113 | try expect(result[0] == 0x2c48); | |
| 114 | try expect(result[1] == 0xa2c4); | |
| 115 | } | |
| 116 | ||
| 117 | test "bitReverse vectors u16" { | |
| 118 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | |
| 119 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 120 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 121 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 122 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 123 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 124 | ||
| 125 | comptime try vector16(); | |
| 126 | try vector16(); | |
| 127 | } | |
| 128 | ||
| 129 | fn vector24() !void { | |
| 130 | var v = @Vector(2, u24){ 0x123456, 0x234567 }; | |
| 131 | var result = @bitReverse(u24, v); | |
| 132 | try expect(result[0] == 0x6a2c48); | |
| 133 | try expect(result[1] == 0xe6a2c4); | |
| 134 | } | |
| 135 | ||
| 136 | test "bitReverse vectors u24" { | |
| 137 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | |
| 138 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 139 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 140 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 141 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 142 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 143 | ||
| 144 | comptime try vector24(); | |
| 145 | try vector24(); | |
| 146 | } | |
| 147 | ||
| 148 | fn vector0() !void { | |
| 149 | var v = @Vector(2, u0){ 0, 0 }; | |
| 150 | var result = @bitReverse(u0, v); | |
| 151 | try expect(result[0] == 0); | |
| 152 | try expect(result[1] == 0); | |
| 153 | } | |
| 154 | ||
| 155 | test "bitReverse vectors u0" { | |
| 156 | if (builtin.zig_backend == .stage1) return error.SkipZigTest; | |
| 157 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 158 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 159 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | |
| 160 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | |
| 161 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | |
| 162 | ||
| 163 | comptime try vector0(); | |
| 164 | try vector0(); | |
| 165 | } |