| author | |
| committer | |
| log | 226fcd7c709ec664c5d883042cf7beb3026f66cb |
| tree | 200bd4f31e1328d7a94a106a437d3d0ebd0b9569 |
| parent | 6dcfbfbfb2103082603f34fd5bd7c26616eda8c1 |
3 files changed, 54 insertions(+), 4 deletions(-)
src/codegen/c.zig+22-2| ... | @@ -1708,8 +1708,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO | ... | @@ -1708,8 +1708,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO |
| 1708 | .memcpy => try airMemcpy(f, inst), | 1708 | .memcpy => try airMemcpy(f, inst), |
| 1709 | .set_union_tag => try airSetUnionTag(f, inst), | 1709 | .set_union_tag => try airSetUnionTag(f, inst), |
| 1710 | .get_union_tag => try airGetUnionTag(f, inst), | 1710 | .get_union_tag => try airGetUnionTag(f, inst), |
| 1711 | .clz => try airBuiltinCall(f, inst, "clz"), | 1711 | .clz => try airCountZeroes(f, inst, "clz"), |
| 1712 | .ctz => try airBuiltinCall(f, inst, "ctz"), | 1712 | .ctz => try airCountZeroes(f, inst, "ctz"), |
| 1713 | .popcount => try airBuiltinCall(f, inst, "popcount"), | 1713 | .popcount => try airBuiltinCall(f, inst, "popcount"), |
| 1714 | .byte_swap => try airBuiltinCall(f, inst, "byte_swap"), | 1714 | .byte_swap => try airBuiltinCall(f, inst, "byte_swap"), |
| 1715 | .bit_reverse => try airBuiltinCall(f, inst, "bit_reverse"), | 1715 | .bit_reverse => try airBuiltinCall(f, inst, "bit_reverse"), |
| ... | @@ -3349,6 +3349,26 @@ fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !C | ... | @@ -3349,6 +3349,26 @@ fn airBuiltinCall(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !C |
| 3349 | return local; | 3349 | return local; |
| 3350 | } | 3350 | } |
| 3351 | 3351 | ||
| 3352 | fn airCountZeroes(f: *Function, inst: Air.Inst.Index, fn_name: [*:0]const u8) !CValue { | ||
| 3353 | if (f.liveness.isUnused(inst)) return CValue.none; | ||
| 3354 | |||
| 3355 | const inst_ty = f.air.typeOfIndex(inst); | ||
| 3356 | const local = try f.allocLocal(inst_ty, .Const); | ||
| 3357 | const operand = f.air.instructions.items(.data)[inst].ty_op.operand; | ||
| 3358 | const operand_ty = f.air.typeOf(operand); | ||
| 3359 | const target = f.object.dg.module.getTarget(); | ||
| 3360 | const writer = f.object.writer(); | ||
| 3361 | |||
| 3362 | const zig_bits = operand_ty.intInfo(target).bits; | ||
| 3363 | _ = toCIntBits(zig_bits) orelse | ||
| 3364 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); | ||
| 3365 | |||
| 3366 | try writer.print(" = zig_{s}(", .{fn_name}); | ||
| 3367 | try f.writeCValue(writer, try f.resolveInst(operand)); | ||
| 3368 | try writer.print(", {d});\n", .{zig_bits}); | ||
| 3369 | return local; | ||
| 3370 | } | ||
| 3371 | |||
| 3352 | fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue { | 3372 | fn airCmpxchg(f: *Function, inst: Air.Inst.Index, flavor: [*:0]const u8) !CValue { |
| 3353 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; | 3373 | const ty_pl = f.air.instructions.items(.data)[inst].ty_pl; |
| 3354 | const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | 3374 | const extra = f.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
src/link/C/zig.h+18| ... | @@ -500,3 +500,21 @@ zig_shl_sat_s(isize, intptr_t, ((sizeof(intptr_t)) * CHAR_BIT - 1)) | ... | @@ -500,3 +500,21 @@ zig_shl_sat_s(isize, intptr_t, ((sizeof(intptr_t)) * CHAR_BIT - 1)) |
| 500 | zig_shl_sat_s(short, short, ((sizeof(short )) * CHAR_BIT - 1)) | 500 | zig_shl_sat_s(short, short, ((sizeof(short )) * CHAR_BIT - 1)) |
| 501 | zig_shl_sat_s(int, int, ((sizeof(int )) * CHAR_BIT - 1)) | 501 | zig_shl_sat_s(int, int, ((sizeof(int )) * CHAR_BIT - 1)) |
| 502 | zig_shl_sat_s(long, long, ((sizeof(long )) * CHAR_BIT - 1)) | 502 | zig_shl_sat_s(long, long, ((sizeof(long )) * CHAR_BIT - 1)) |
| 503 | |||
| 504 | #define zig_bitsizeof(T) (CHAR_BIT * sizeof(T)) | ||
| 505 | |||
| 506 | static inline int zig_clz(uint64_t value, uint8_t zig_type_bit_width) { | ||
| 507 | if (value == 0) return zig_type_bit_width; | ||
| 508 | if (zig_type_bit_width <= zig_bitsizeof(unsigned int)) | ||
| 509 | return (__builtin_clz(value) - zig_bitsizeof(unsigned int) + zig_type_bit_width); | ||
| 510 | if (zig_type_bit_width <= zig_bitsizeof(unsigned long)) | ||
| 511 | return (__builtin_clzl(value) - zig_bitsizeof(unsigned long) + zig_type_bit_width); | ||
| 512 | return (__builtin_clzll(value) - zig_bitsizeof(unsigned long long) + zig_type_bit_width); | ||
| 513 | } | ||
| 514 | |||
| 515 | static inline int zig_ctz(uint64_t value, uint8_t zig_type_bit_width) { | ||
| 516 | if (value == 0) return zig_type_bit_width; | ||
| 517 | if (zig_type_bit_width <= zig_bitsizeof(unsigned int)) return __builtin_ctz(value); | ||
| 518 | if (zig_type_bit_width <= zig_bitsizeof(unsigned long)) return __builtin_ctzl(value); | ||
| 519 | return __builtin_ctzll(value); | ||
| 520 | } |
test/behavior/math.zig+14-2| ... | @@ -65,7 +65,6 @@ test "@clz" { | ... | @@ -65,7 +65,6 @@ test "@clz" { |
| 65 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 65 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 66 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 66 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 67 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 67 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 68 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 69 | 68 | ||
| 70 | try testClz(); | 69 | try testClz(); |
| 71 | comptime try testClz(); | 70 | comptime try testClz(); |
| ... | @@ -76,6 +75,20 @@ fn testClz() !void { | ... | @@ -76,6 +75,20 @@ fn testClz() !void { |
| 76 | try expect(testOneClz(u8, 0b00001010) == 4); | 75 | try expect(testOneClz(u8, 0b00001010) == 4); |
| 77 | try expect(testOneClz(u8, 0b00011010) == 3); | 76 | try expect(testOneClz(u8, 0b00011010) == 3); |
| 78 | try expect(testOneClz(u8, 0b00000000) == 8); | 77 | try expect(testOneClz(u8, 0b00000000) == 8); |
| 78 | } | ||
| 79 | |||
| 80 | test "@clz big ints" { | ||
| 81 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 82 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 83 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 84 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 85 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 86 | |||
| 87 | try testClzBigInts(); | ||
| 88 | comptime try testClzBigInts(); | ||
| 89 | } | ||
| 90 | |||
| 91 | fn testClzBigInts() !void { | ||
| 79 | try expect(testOneClz(u128, 0xffffffffffffffff) == 64); | 92 | try expect(testOneClz(u128, 0xffffffffffffffff) == 64); |
| 80 | try expect(testOneClz(u128, 0x10000000000000000) == 63); | 93 | try expect(testOneClz(u128, 0x10000000000000000) == 63); |
| 81 | } | 94 | } |
| ... | @@ -130,7 +143,6 @@ test "@ctz" { | ... | @@ -130,7 +143,6 @@ test "@ctz" { |
| 130 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 143 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 131 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 144 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 132 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 145 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 133 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 134 | 146 | ||
| 135 | try testCtz(); | 147 | try testCtz(); |
| 136 | comptime try testCtz(); | 148 | comptime try testCtz(); |