From 0746028a2a6caf28e396f042be0b23c8d6fb7a5e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 21 Apr 2020 17:54:00 -0400 Subject: [PATCH] ir: analyze int instruction --- src-self-hosted/ir.zig | 52 ++++++++++++++++++++++++++++++++++++++- src-self-hosted/value.zig | 9 +++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index e565d253c..01c787201 100644 --- a/src-self-hosted/ir.zig +++ b/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)}), diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig index 8d3aa5daf..cd87fe24f 100644 --- a/src-self-hosted/value.zig +++ b/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`