Commit 77d06012c2

Jacob Young <jacobly0@users.noreply.github.com>
2023-03-07 08:59:41
CBE: implement unsigned big int div and mod
1 parent c1d16a2
Changed files (3)
lib
src
codegen
test
behavior
lib/zig.h
@@ -2384,6 +2384,44 @@ static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, boo
     (void)zig_subo_big(res, lhs, rhs, is_signed, bits);
 }
 
+zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
+static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
+    if (!is_signed) {
+        __udivei4(res, lhs, rhs, bits);
+        return;
+    }
+
+    zig_trap();
+}
+
+static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
+    if (!is_signed) {
+        zig_div_trunc_big(res, lhs, rhs, is_signed, bits);
+        return;
+    }
+
+    zig_trap();
+}
+
+zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
+static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
+    if (!is_signed) {
+        __umodei4(res, lhs, rhs, bits);
+        return;
+    }
+
+    zig_trap();
+}
+
+static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
+    if (!is_signed) {
+        zig_rem_big(res, lhs, rhs, is_signed, bits);
+        return;
+    }
+
+    zig_trap();
+}
+
 static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) {
     const uint8_t *val_bytes = val;
     uint16_t byte_offset = 0;
src/codegen/c.zig
@@ -1885,25 +1885,28 @@ pub const DeclGen = struct {
     }
 
     fn renderBuiltinInfo(dg: *DeclGen, writer: anytype, ty: Type, info: BuiltinInfo) !void {
+        const cty = try dg.typeToCType(ty, .complete);
+        const is_big = cty.tag() == .array;
+
         switch (info) {
-            .none => {},
-            .bits => {
-                const target = dg.module.getTarget();
-                const int_info = if (ty.isAbiInt()) ty.intInfo(target) else std.builtin.Type.Int{
-                    .signedness = .unsigned,
-                    .bits = @intCast(u16, ty.bitSize(target)),
-                };
+            .none => if (!is_big) return,
+            .bits => {},
+        }
 
-                const cty = try dg.typeToCType(ty, .complete);
-                if (cty.tag() == .array) try writer.print(", {}", .{int_info.signedness == .signed});
+        const target = dg.module.getTarget();
+        const int_info = if (ty.isAbiInt()) ty.intInfo(target) else std.builtin.Type.Int{
+            .signedness = .unsigned,
+            .bits = @intCast(u16, ty.bitSize(target)),
+        };
 
-                var bits_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = int_info.bits };
-                try writer.print(", {}", .{try dg.fmtIntLiteral(switch (cty.tag()) {
-                    else => Type.u8,
-                    .array => Type.u16,
-                }, Value.initPayload(&bits_pl.base), .FunctionArgument)});
-            },
-        }
+        if (is_big) try writer.print(", {}", .{int_info.signedness == .signed});
+
+        var bits_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = int_info.bits };
+        try writer.print(", {}", .{try dg.fmtIntLiteral(
+            if (is_big) Type.u16 else Type.u8,
+            Value.initPayload(&bits_pl.base),
+            .FunctionArgument,
+        )});
     }
 
     fn fmtIntLiteral(
@@ -6099,13 +6102,16 @@ fn airBinBuiltinCall(
         return .none;
     }
 
+    const operand_ty = f.air.typeOf(bin_op.lhs);
+    const operand_cty = try f.typeToCType(operand_ty, .complete);
+    const is_big = operand_cty.tag() == .array;
+
     const lhs = try f.resolveInst(bin_op.lhs);
     const rhs = try f.resolveInst(bin_op.rhs);
-    try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
+    if (!is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
 
     const inst_ty = f.air.typeOfIndex(inst);
     const inst_scalar_ty = inst_ty.scalarType();
-    const operand_ty = f.air.typeOf(bin_op.lhs);
     const scalar_ty = operand_ty.scalarType();
 
     const inst_scalar_cty = try f.typeToCType(inst_scalar_ty, .complete);
@@ -6113,6 +6119,7 @@ fn airBinBuiltinCall(
 
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, inst_ty);
+    if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
     const v = try Vectorizer.start(f, inst, writer, operand_ty);
     if (!ref_ret) {
         try f.writeCValue(writer, local, .Other);
test/behavior/int_div.zig
@@ -95,7 +95,6 @@ fn rem(comptime T: type, a: T, b: T) T {
 test "large integer division" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
-    if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;