| ... | @@ -5,6 +5,7 @@ const Value = @import("value.zig").Value; | ... | @@ -5,6 +5,7 @@ const Value = @import("value.zig").Value; |
| 5 | const Type = @import("type.zig").Type; | 5 | const Type = @import("type.zig").Type; |
| 6 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| 7 | const text = @import("ir/text.zig"); | 7 | const text = @import("ir/text.zig"); |
| | 8 | const BigInt = std.math.big.Int; |
| 8 | | 9 | |
| 9 | /// These are in-memory, analyzed instructions. See `text.Inst` for the representation | 10 | /// These are in-memory, analyzed instructions. See `text.Inst` for the representation |
| 10 | /// of instructions that correspond to the ZIR text format. | 11 | /// of instructions that correspond to the ZIR text format. |
| ... | @@ -267,6 +268,52 @@ const Analyze = struct { | ... | @@ -267,6 +268,52 @@ const Analyze = struct { |
| 267 | }); | 268 | }); |
| 268 | } | 269 | } |
| 269 | | 270 | |
| | 271 | fn constIntUnsigned(self: *Analyze, src: usize, ty: Type, int: u64) !*Inst { |
| | 272 | const int_payload = try self.arena.allocator.create(Value.Payload.Int_u64); |
| | 273 | int_payload.* = .{ .int = int }; |
| | 274 | |
| | 275 | return self.constInst(src, .{ |
| | 276 | .ty = ty, |
| | 277 | .val = Value.initPayload(&int_payload.base), |
| | 278 | }); |
| | 279 | } |
| | 280 | |
| | 281 | fn constIntSigned(self: *Analyze, src: usize, ty: Type, int: i64) !*Inst { |
| | 282 | const int_payload = try self.arena.allocator.create(Value.Payload.Int_i64); |
| | 283 | int_payload.* = .{ .int = int }; |
| | 284 | |
| | 285 | return self.constInst(src, .{ |
| | 286 | .ty = ty, |
| | 287 | .val = Value.initPayload(&int_payload.base), |
| | 288 | }); |
| | 289 | } |
| | 290 | |
| | 291 | fn constIntBig(self: *Analyze, src: usize, ty: Type, big_int: BigInt) !*Inst { |
| | 292 | if (big_int.isPositive()) { |
| | 293 | if (big_int.to(u64)) |x| { |
| | 294 | return self.constIntUnsigned(src, ty, x); |
| | 295 | } else |err| switch (err) { |
| | 296 | error.NegativeIntoUnsigned => unreachable, |
| | 297 | error.TargetTooSmall => {}, // handled below |
| | 298 | } |
| | 299 | } else { |
| | 300 | if (big_int.to(i64)) |x| { |
| | 301 | return self.constIntSigned(src, ty, x); |
| | 302 | } else |err| switch (err) { |
| | 303 | error.NegativeIntoUnsigned => unreachable, |
| | 304 | error.TargetTooSmall => {}, // handled below |
| | 305 | } |
| | 306 | } |
| | 307 | |
| | 308 | const big_int_payload = try self.arena.allocator.create(Value.Payload.IntBig); |
| | 309 | big_int_payload.* = .{ .big_int = big_int }; |
| | 310 | |
| | 311 | return self.constInst(src, .{ |
| | 312 | .ty = ty, |
| | 313 | .val = Value.initPayload(&big_int_payload.base), |
| | 314 | }); |
| | 315 | } |
| | 316 | |
| 270 | fn analyzeInst(self: *Analyze, func: ?*Fn, old_inst: *text.Inst) InnerError!*Inst { | 317 | fn analyzeInst(self: *Analyze, func: ?*Fn, old_inst: *text.Inst) InnerError!*Inst { |
| 271 | switch (old_inst.tag) { | 318 | switch (old_inst.tag) { |
| 272 | .str => { | 319 | .str => { |
| ... | @@ -275,7 +322,10 @@ const Analyze = struct { | ... | @@ -275,7 +322,10 @@ const Analyze = struct { |
| 275 | const bytes = old_inst.cast(text.Inst.Str).?.positionals.bytes; | 322 | const bytes = old_inst.cast(text.Inst.Str).?.positionals.bytes; |
| 276 | return self.constStr(old_inst.src, bytes); | 323 | return self.constStr(old_inst.src, bytes); |
| 277 | }, | 324 | }, |
| 278 | .int => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), | 325 | .int => { |
| | 326 | const big_int = old_inst.cast(text.Inst.Int).?.positionals.int; |
| | 327 | return self.constIntBig(old_inst.src, Type.initTag(.comptime_int), big_int); |
| | 328 | }, |
| 279 | .ptrtoint => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), | 329 | .ptrtoint => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), |
| 280 | .fieldptr => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), | 330 | .fieldptr => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), |
| 281 | .deref => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), | 331 | .deref => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), |