Commit 0746028a2a

Andrew Kelley <andrew@ziglang.org>
2020-04-21 23:54:00
ir: analyze int instruction
1 parent 6987820
Changed files (2)
src-self-hosted
src-self-hosted/ir.zig
@@ -5,6 +5,7 @@ const Value = @import("value.zig").Value;
 const Type = @import("type.zig").Type;
 const assert = std.debug.assert;
 const text = @import("ir/text.zig");
+const BigInt = std.math.big.Int;
 
 /// These are in-memory, analyzed instructions. See `text.Inst` for the representation
 /// of instructions that correspond to the ZIR text format.
@@ -267,6 +268,52 @@ const Analyze = struct {
         });
     }
 
+    fn constIntUnsigned(self: *Analyze, src: usize, ty: Type, int: u64) !*Inst {
+        const int_payload = try self.arena.allocator.create(Value.Payload.Int_u64);
+        int_payload.* = .{ .int = int };
+
+        return self.constInst(src, .{
+            .ty = ty,
+            .val = Value.initPayload(&int_payload.base),
+        });
+    }
+
+    fn constIntSigned(self: *Analyze, src: usize, ty: Type, int: i64) !*Inst {
+        const int_payload = try self.arena.allocator.create(Value.Payload.Int_i64);
+        int_payload.* = .{ .int = int };
+
+        return self.constInst(src, .{
+            .ty = ty,
+            .val = Value.initPayload(&int_payload.base),
+        });
+    }
+
+    fn constIntBig(self: *Analyze, src: usize, ty: Type, big_int: BigInt) !*Inst {
+        if (big_int.isPositive()) {
+            if (big_int.to(u64)) |x| {
+                return self.constIntUnsigned(src, ty, x);
+            } else |err| switch (err) {
+                error.NegativeIntoUnsigned => unreachable,
+                error.TargetTooSmall => {}, // handled below
+            }
+        } else {
+            if (big_int.to(i64)) |x| {
+                return self.constIntSigned(src, ty, x);
+            } else |err| switch (err) {
+                error.NegativeIntoUnsigned => unreachable,
+                error.TargetTooSmall => {}, // handled below
+            }
+        }
+
+        const big_int_payload = try self.arena.allocator.create(Value.Payload.IntBig);
+        big_int_payload.* = .{ .big_int = big_int };
+
+        return self.constInst(src, .{
+            .ty = ty,
+            .val = Value.initPayload(&big_int_payload.base),
+        });
+    }
+
     fn analyzeInst(self: *Analyze, func: ?*Fn, old_inst: *text.Inst) InnerError!*Inst {
         switch (old_inst.tag) {
             .str => {
@@ -275,7 +322,10 @@ const Analyze = struct {
                 const bytes = old_inst.cast(text.Inst.Str).?.positionals.bytes;
                 return self.constStr(old_inst.src, bytes);
             },
-            .int => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
+            .int => {
+                const big_int = old_inst.cast(text.Inst.Int).?.positionals.int;
+                return self.constIntBig(old_inst.src, Type.initTag(.comptime_int), big_int);
+            },
             .ptrtoint => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
             .fieldptr => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
             .deref => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}),
src-self-hosted/value.zig
@@ -2,6 +2,7 @@ const std = @import("std");
 const Type = @import("type.zig").Type;
 const log2 = std.math.log2;
 const assert = std.debug.assert;
+const BigInt = std.math.big.Int;
 
 /// This is the raw data, with no bookkeeping, no memory awareness,
 /// no de-duplication, and no type system awareness.
@@ -53,6 +54,7 @@ pub const Value = extern union {
         ty,
         int_u64,
         int_i64,
+        int_big,
         function,
         ref,
         bytes,
@@ -133,6 +135,7 @@ pub const Value = extern union {
             .ty => return self.cast(Payload.Ty).?.ty.format("", options, out_stream),
             .int_u64 => return std.fmt.formatIntValue(self.cast(Payload.Int_u64).?.int, "", options, out_stream),
             .int_i64 => return std.fmt.formatIntValue(self.cast(Payload.Int_i64).?.int, "", options, out_stream),
+            .int_big => return out_stream.print("{}", .{self.cast(Payload.IntBig).?.big_int}),
             .function => return out_stream.writeAll("(function)"),
             .ref => return out_stream.writeAll("(ref)"),
             .bytes => return std.zig.renderStringLiteral(self.cast(Payload.Bytes).?.data, out_stream),
@@ -187,6 +190,7 @@ pub const Value = extern union {
             .bool_false,
             .int_u64,
             .int_i64,
+            .int_big,
             .function,
             .ref,
             .bytes,
@@ -208,6 +212,11 @@ pub const Value = extern union {
             int: i64,
         };
 
+        pub const IntBig = struct {
+            base: Payload = Payload{ .tag = .int_big },
+            big_int: BigInt,
+        };
+
         pub const Function = struct {
             base: Payload = Payload{ .tag = .function },
             /// Index into the `fns` array of the `ir.Module`