authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-07 02:59:41-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-07 03:03:35-05:00
log77d06012c2465f7c4ac22cb4834a2535c4de6cea
tree1b29914bb1c538c78a472f6a16b79f3688912d32
parentc1d16a2b80e258a126ed496dab09a8a7c26f8468

CBE: implement unsigned big int div and mod


3 files changed, 63 insertions(+), 19 deletions(-)

lib/zig.h+38
...@@ -2384,6 +2384,44 @@ static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, boo...@@ -2384,6 +2384,44 @@ static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, boo
2384 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);2384 (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
2385}2385}
23862386
2387zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
2388static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2389 if (!is_signed) {
2390 __udivei4(res, lhs, rhs, bits);
2391 return;
2392 }
2393
2394 zig_trap();
2395}
2396
2397static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2398 if (!is_signed) {
2399 zig_div_trunc_big(res, lhs, rhs, is_signed, bits);
2400 return;
2401 }
2402
2403 zig_trap();
2404}
2405
2406zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
2407static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2408 if (!is_signed) {
2409 __umodei4(res, lhs, rhs, bits);
2410 return;
2411 }
2412
2413 zig_trap();
2414}
2415
2416static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
2417 if (!is_signed) {
2418 zig_rem_big(res, lhs, rhs, is_signed, bits);
2419 return;
2420 }
2421
2422 zig_trap();
2423}
2424
2387static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) {2425static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) {
2388 const uint8_t *val_bytes = val;2426 const uint8_t *val_bytes = val;
2389 uint16_t byte_offset = 0;2427 uint16_t byte_offset = 0;
src/codegen/c.zig+25-18
...@@ -1885,25 +1885,28 @@ pub const DeclGen = struct {...@@ -1885,25 +1885,28 @@ pub const DeclGen = struct {
1885 }1885 }
18861886
1887 fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void {1887 fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void {
1888 const cty = try dg.typeToCType(ty, .complete);
1889 const is_big = cty.tag() == .array;
1890
1888 switch (info) {1891 switch (info) {
1889 .none => {},1892 .none => if (!is_big) return,
1890 .bits => {1893 .bits => {},
1891 const target = dg.module.getTarget();1894 }
1892 const int_info = if (ty.isAbiInt()) ty.intInfo(target) else std.builtin.Type.Int{
1893 .signedness = .unsigned,
1894 .bits = @intCast(u16, ty.bitSize(target)),
1895 };
18961895
1897 const cty = try dg.typeToCType(ty, .complete);1896 const target = dg.module.getTarget();
1898 if (cty.tag() == .array) try writer.print(", {}", .{int_info.signedness == .signed});1897 const int_info = if (ty.isAbiInt()) ty.intInfo(target) else std.builtin.Type.Int{
1898 .signedness = .unsigned,
1899 .bits = @intCast(u16, ty.bitSize(target)),
1900 };
18991901
1900 var bits_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = int_info.bits };1902 if (is_big) try writer.print(", {}", .{int_info.signedness == .signed});
1901 try writer.print(", {}", .{try dg.fmtIntLiteral(switch (cty.tag()) {1903
1902 else => Type.u8,1904 var bits_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = int_info.bits };
1903 .array => Type.u16,1905 try writer.print(", {}", .{try dg.fmtIntLiteral(
1904 }, Value.initPayload(&bits_pl.base), .FunctionArgument)});1906 if (is_big) Type.u16 else Type.u8,
1905 },1907 Value.initPayload(&bits_pl.base),
1906 }1908 .FunctionArgument,
1909 )});
1907 }1910 }
19081911
1909 fn fmtIntLiteral(1912 fn fmtIntLiteral(
...@@ -6099,13 +6102,16 @@ fn airBinBuiltinCall(...@@ -6099,13 +6102,16 @@ fn airBinBuiltinCall(
6099 return .none;6102 return .none;
6100 }6103 }
61016104
6105 const operand_ty = f.air.typeOf(bin_op.lhs);
6106 const operand_cty = try f.typeToCType(operand_ty, .complete);
6107 const is_big = operand_cty.tag() == .array;
6108
6102 const lhs = try f.resolveInst(bin_op.lhs);6109 const lhs = try f.resolveInst(bin_op.lhs);
6103 const rhs = try f.resolveInst(bin_op.rhs);6110 const rhs = try f.resolveInst(bin_op.rhs);
6104 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });6111 if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
61056112
6106 const inst_ty = f.air.typeOfIndex(inst);6113 const inst_ty = f.air.typeOfIndex(inst);
6107 const inst_scalar_ty = inst_ty.scalarType();6114 const inst_scalar_ty = inst_ty.scalarType();
6108 const operand_ty = f.air.typeOf(bin_op.lhs);
6109 const scalar_ty = operand_ty.scalarType();6115 const scalar_ty = operand_ty.scalarType();
61106116
6111 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);6117 const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
...@@ -6113,6 +6119,7 @@ fn airBinBuiltinCall(...@@ -6113,6 +6119,7 @@ fn airBinBuiltinCall(
61136119
6114 const writer = f.object.writer();6120 const writer = f.object.writer();
6115 const local = try f.allocLocal(inst, inst_ty);6121 const local = try f.allocLocal(inst, inst_ty);
6122 if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
6116 const v = try Vectorizer.start(f, inst, writer, operand_ty);6123 const v = try Vectorizer.start(f, inst, writer, operand_ty);
6117 if (!ref_ret) {6124 if (!ref_ret) {
6118 try f.writeCValue(writer, local, .Other);6125 try f.writeCValue(writer, local, .Other);
test/behavior/int_div.zig-1
...@@ -95,7 +95,6 @@ fn rem(comptime T: type, a: T, b: T) T {...@@ -95,7 +95,6 @@ fn rem(comptime T: type, a: T, b: T) T {
95test "large integer division" {95test "large integer division" {
96 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;96 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
97 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;97 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
98 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
99 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;98 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
100 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;99 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
101 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;100 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;