| author | |
| committer | |
| log | 2cdbb5f47260d2510ce478c77fa9c3c7c29fb671 |
| tree | 6bebbf19524eaad49c86dbfd8cbc43e2e27375bb |
| parent | 0746028a2a6caf28e396f042be0b23c8d6fb7a5e |
8 files changed, 303 insertions(+), 174 deletions(-)
lib/std/math/big/int.zig+1-1| ... | ... | @@ -237,7 +237,7 @@ pub const Int = struct { |
| 237 | 237 | return bits; |
| 238 | 238 | } |
| 239 | 239 | |
| 240 | fn fitsInTwosComp(self: Int, is_signed: bool, bit_count: usize) bool { | |
| 240 | pub fn fitsInTwosComp(self: Int, is_signed: bool, bit_count: usize) bool { | |
| 241 | 241 | if (self.eqZero()) { |
| 242 | 242 | return true; |
| 243 | 243 | } |
lib/std/target.zig+1-1| ... | ... | @@ -761,7 +761,7 @@ pub const Target = struct { |
| 761 | 761 | }; |
| 762 | 762 | } |
| 763 | 763 | |
| 764 | pub fn ptrBitWidth(arch: Arch) u32 { | |
| 764 | pub fn ptrBitWidth(arch: Arch) u16 { | |
| 765 | 765 | switch (arch) { |
| 766 | 766 | .avr, |
| 767 | 767 | .msp430, |
src-self-hosted/c_int.zig deleted-169| ... | ... | @@ -1,169 +0,0 @@ |
| 1 | const Target = @import("std").Target; | |
| 2 | ||
| 3 | pub const CInt = struct { | |
| 4 | id: Id, | |
| 5 | zig_name: []const u8, | |
| 6 | c_name: []const u8, | |
| 7 | is_signed: bool, | |
| 8 | ||
| 9 | pub const Id = enum { | |
| 10 | Short, | |
| 11 | UShort, | |
| 12 | Int, | |
| 13 | UInt, | |
| 14 | Long, | |
| 15 | ULong, | |
| 16 | LongLong, | |
| 17 | ULongLong, | |
| 18 | }; | |
| 19 | ||
| 20 | pub const list = [_]CInt{ | |
| 21 | CInt{ | |
| 22 | .id = .Short, | |
| 23 | .zig_name = "c_short", | |
| 24 | .c_name = "short", | |
| 25 | .is_signed = true, | |
| 26 | }, | |
| 27 | CInt{ | |
| 28 | .id = .UShort, | |
| 29 | .zig_name = "c_ushort", | |
| 30 | .c_name = "unsigned short", | |
| 31 | .is_signed = false, | |
| 32 | }, | |
| 33 | CInt{ | |
| 34 | .id = .Int, | |
| 35 | .zig_name = "c_int", | |
| 36 | .c_name = "int", | |
| 37 | .is_signed = true, | |
| 38 | }, | |
| 39 | CInt{ | |
| 40 | .id = .UInt, | |
| 41 | .zig_name = "c_uint", | |
| 42 | .c_name = "unsigned int", | |
| 43 | .is_signed = false, | |
| 44 | }, | |
| 45 | CInt{ | |
| 46 | .id = .Long, | |
| 47 | .zig_name = "c_long", | |
| 48 | .c_name = "long", | |
| 49 | .is_signed = true, | |
| 50 | }, | |
| 51 | CInt{ | |
| 52 | .id = .ULong, | |
| 53 | .zig_name = "c_ulong", | |
| 54 | .c_name = "unsigned long", | |
| 55 | .is_signed = false, | |
| 56 | }, | |
| 57 | CInt{ | |
| 58 | .id = .LongLong, | |
| 59 | .zig_name = "c_longlong", | |
| 60 | .c_name = "long long", | |
| 61 | .is_signed = true, | |
| 62 | }, | |
| 63 | CInt{ | |
| 64 | .id = .ULongLong, | |
| 65 | .zig_name = "c_ulonglong", | |
| 66 | .c_name = "unsigned long long", | |
| 67 | .is_signed = false, | |
| 68 | }, | |
| 69 | }; | |
| 70 | ||
| 71 | pub fn sizeInBits(cint: CInt, self: Target) u32 { | |
| 72 | const arch = self.cpu.arch; | |
| 73 | switch (self.os.tag) { | |
| 74 | .freestanding, .other => switch (self.cpu.arch) { | |
| 75 | .msp430 => switch (cint.id) { | |
| 76 | .Short, | |
| 77 | .UShort, | |
| 78 | .Int, | |
| 79 | .UInt, | |
| 80 | => return 16, | |
| 81 | .Long, | |
| 82 | .ULong, | |
| 83 | => return 32, | |
| 84 | .LongLong, | |
| 85 | .ULongLong, | |
| 86 | => return 64, | |
| 87 | }, | |
| 88 | else => switch (cint.id) { | |
| 89 | .Short, | |
| 90 | .UShort, | |
| 91 | => return 16, | |
| 92 | .Int, | |
| 93 | .UInt, | |
| 94 | => return 32, | |
| 95 | .Long, | |
| 96 | .ULong, | |
| 97 | => return self.cpu.arch.ptrBitWidth(), | |
| 98 | .LongLong, | |
| 99 | .ULongLong, | |
| 100 | => return 64, | |
| 101 | }, | |
| 102 | }, | |
| 103 | ||
| 104 | .linux, | |
| 105 | .macosx, | |
| 106 | .freebsd, | |
| 107 | .openbsd, | |
| 108 | => switch (cint.id) { | |
| 109 | .Short, | |
| 110 | .UShort, | |
| 111 | => return 16, | |
| 112 | .Int, | |
| 113 | .UInt, | |
| 114 | => return 32, | |
| 115 | .Long, | |
| 116 | .ULong, | |
| 117 | => return self.cpu.arch.ptrBitWidth(), | |
| 118 | .LongLong, | |
| 119 | .ULongLong, | |
| 120 | => return 64, | |
| 121 | }, | |
| 122 | ||
| 123 | .windows, .uefi => switch (cint.id) { | |
| 124 | .Short, | |
| 125 | .UShort, | |
| 126 | => return 16, | |
| 127 | .Int, | |
| 128 | .UInt, | |
| 129 | => return 32, | |
| 130 | .Long, | |
| 131 | .ULong, | |
| 132 | .LongLong, | |
| 133 | .ULongLong, | |
| 134 | => return 64, | |
| 135 | }, | |
| 136 | ||
| 137 | .ananas, | |
| 138 | .cloudabi, | |
| 139 | .dragonfly, | |
| 140 | .fuchsia, | |
| 141 | .ios, | |
| 142 | .kfreebsd, | |
| 143 | .lv2, | |
| 144 | .netbsd, | |
| 145 | .solaris, | |
| 146 | .haiku, | |
| 147 | .minix, | |
| 148 | .rtems, | |
| 149 | .nacl, | |
| 150 | .cnk, | |
| 151 | .aix, | |
| 152 | .cuda, | |
| 153 | .nvcl, | |
| 154 | .amdhsa, | |
| 155 | .ps4, | |
| 156 | .elfiamcu, | |
| 157 | .tvos, | |
| 158 | .watchos, | |
| 159 | .mesa3d, | |
| 160 | .contiki, | |
| 161 | .amdpal, | |
| 162 | .hermit, | |
| 163 | .hurd, | |
| 164 | .wasi, | |
| 165 | .emscripten, | |
| 166 | => @panic("TODO specify the C integer type sizes for this OS"), | |
| 167 | } | |
| 168 | } | |
| 169 | }; |
src-self-hosted/ir.zig+49| ... | ... | @@ -6,6 +6,7 @@ const Type = @import("type.zig").Type; |
| 6 | 6 | const assert = std.debug.assert; |
| 7 | 7 | const text = @import("ir/text.zig"); |
| 8 | 8 | const BigInt = std.math.big.Int; |
| 9 | const Target = std.Target; | |
| 9 | 10 | |
| 10 | 11 | /// These are in-memory, analyzed instructions. See `text.Inst` for the representation |
| 11 | 12 | /// of instructions that correspond to the ZIR text format. |
| ... | ... | @@ -99,6 +100,8 @@ pub const ErrorMsg = struct { |
| 99 | 100 | }; |
| 100 | 101 | |
| 101 | 102 | pub fn analyze(allocator: *Allocator, old_module: text.Module) !Module { |
| 103 | const native_info = try std.zig.system.NativeTargetInfo.detect(allocator, .{}); | |
| 104 | ||
| 102 | 105 | var ctx = Analyze{ |
| 103 | 106 | .allocator = allocator, |
| 104 | 107 | .arena = std.heap.ArenaAllocator.init(allocator), |
| ... | ... | @@ -107,6 +110,7 @@ pub fn analyze(allocator: *Allocator, old_module: text.Module) !Module { |
| 107 | 110 | .decl_table = std.AutoHashMap(*text.Inst, Analyze.NewDecl).init(allocator), |
| 108 | 111 | .exports = std.ArrayList(Module.Export).init(allocator), |
| 109 | 112 | .fns = std.ArrayList(Module.Fn).init(allocator), |
| 113 | .target = native_info.target, | |
| 110 | 114 | }; |
| 111 | 115 | defer ctx.errors.deinit(); |
| 112 | 116 | defer ctx.decl_table.deinit(); |
| ... | ... | @@ -135,6 +139,7 @@ const Analyze = struct { |
| 135 | 139 | decl_table: std.AutoHashMap(*text.Inst, NewDecl), |
| 136 | 140 | exports: std.ArrayList(Module.Export), |
| 137 | 141 | fns: std.ArrayList(Module.Fn), |
| 142 | target: Target, | |
| 138 | 143 | |
| 139 | 144 | const NewDecl = struct { |
| 140 | 145 | /// null means a semantic analysis error happened |
| ... | ... | @@ -336,6 +341,7 @@ const Analyze = struct { |
| 336 | 341 | .@"export" => return self.fail(old_inst.src, "TODO implement analyzing {}", .{@tagName(old_inst.tag)}), |
| 337 | 342 | .primitive => return self.analyzeInstPrimitive(func, old_inst.cast(text.Inst.Primitive).?), |
| 338 | 343 | .fntype => return self.analyzeInstFnType(func, old_inst.cast(text.Inst.FnType).?), |
| 344 | .intcast => return self.analyzeInstIntCast(func, old_inst.cast(text.Inst.IntCast).?), | |
| 339 | 345 | } |
| 340 | 346 | } |
| 341 | 347 | |
| ... | ... | @@ -402,6 +408,38 @@ const Analyze = struct { |
| 402 | 408 | return self.coerce(dest_type, new_inst); |
| 403 | 409 | } |
| 404 | 410 | |
| 411 | fn analyzeInstIntCast(self: *Analyze, func: ?*Fn, intcast: *text.Inst.IntCast) InnerError!*Inst { | |
| 412 | const dest_type = try self.resolveType(func, intcast.positionals.dest_type); | |
| 413 | const new_inst = try self.resolveInst(func, intcast.positionals.value); | |
| 414 | ||
| 415 | const dest_is_comptime_int = switch (dest_type.zigTypeTag()) { | |
| 416 | .ComptimeInt => true, | |
| 417 | .Int => false, | |
| 418 | else => return self.fail( | |
| 419 | intcast.positionals.dest_type.src, | |
| 420 | "expected integer type, found '{}'", | |
| 421 | .{ | |
| 422 | dest_type, | |
| 423 | }, | |
| 424 | ), | |
| 425 | }; | |
| 426 | ||
| 427 | switch (new_inst.ty.zigTypeTag()) { | |
| 428 | .ComptimeInt, .Int => {}, | |
| 429 | else => return self.fail( | |
| 430 | intcast.positionals.value.src, | |
| 431 | "expected integer type, found '{}'", | |
| 432 | .{new_inst.ty}, | |
| 433 | ), | |
| 434 | } | |
| 435 | ||
| 436 | if (dest_is_comptime_int or new_inst.value() != null) { | |
| 437 | return self.coerce(dest_type, new_inst); | |
| 438 | } | |
| 439 | ||
| 440 | return self.fail(intcast.base.src, "TODO implement analyze widen or shorten int", .{}); | |
| 441 | } | |
| 442 | ||
| 405 | 443 | fn coerce(self: *Analyze, dest_type: Type, inst: *Inst) !*Inst { |
| 406 | 444 | const in_memory_result = coerceInMemoryAllowed(dest_type, inst.ty); |
| 407 | 445 | if (in_memory_result == .ok) { |
| ... | ... | @@ -420,6 +458,17 @@ const Analyze = struct { |
| 420 | 458 | return self.coerceArrayPtrToSlice(dest_type, inst); |
| 421 | 459 | } |
| 422 | 460 | } |
| 461 | ||
| 462 | // comptime_int to fixed-width integer | |
| 463 | if (inst.ty.zigTypeTag() == .ComptimeInt and dest_type.zigTypeTag() == .Int) { | |
| 464 | // The representation is already correct; we only need to make sure it fits in the destination type. | |
| 465 | const val = inst.value().?; // comptime_int always has comptime known value | |
| 466 | if (!val.intFitsInType(dest_type, self.target)) { | |
| 467 | return self.fail(inst.src, "type {} cannot represent integer value {}", .{ inst.ty, val }); | |
| 468 | } | |
| 469 | return self.constInst(inst.src, .{ .ty = dest_type, .val = val }); | |
| 470 | } | |
| 471 | ||
| 423 | 472 | return self.fail(inst.src, "TODO implement type coercion", .{}); |
| 424 | 473 | } |
| 425 | 474 |
src-self-hosted/ir/text.zig+14| ... | ... | @@ -28,6 +28,7 @@ pub const Inst = struct { |
| 28 | 28 | @"export", |
| 29 | 29 | primitive, |
| 30 | 30 | fntype, |
| 31 | intcast, | |
| 31 | 32 | }; |
| 32 | 33 | |
| 33 | 34 | pub fn TagToType(tag: Tag) type { |
| ... | ... | @@ -44,6 +45,7 @@ pub const Inst = struct { |
| 44 | 45 | .@"export" => Export, |
| 45 | 46 | .primitive => Primitive, |
| 46 | 47 | .fntype => FnType, |
| 48 | .intcast => IntCast, | |
| 47 | 49 | }; |
| 48 | 50 | } |
| 49 | 51 | |
| ... | ... | @@ -243,6 +245,17 @@ pub const Inst = struct { |
| 243 | 245 | cc: std.builtin.CallingConvention = .Unspecified, |
| 244 | 246 | }, |
| 245 | 247 | }; |
| 248 | ||
| 249 | pub const IntCast = struct { | |
| 250 | pub const base_tag = Tag.intcast; | |
| 251 | base: Inst, | |
| 252 | ||
| 253 | positionals: struct { | |
| 254 | dest_type: *Inst, | |
| 255 | value: *Inst, | |
| 256 | }, | |
| 257 | kw_args: struct {}, | |
| 258 | }; | |
| 246 | 259 | }; |
| 247 | 260 | |
| 248 | 261 | pub const ErrorMsg = struct { |
| ... | ... | @@ -315,6 +328,7 @@ pub const Module = struct { |
| 315 | 328 | .@"export" => return self.writeInstToStreamGeneric(stream, .@"export", decl, inst_table), |
| 316 | 329 | .primitive => return self.writeInstToStreamGeneric(stream, .primitive, decl, inst_table), |
| 317 | 330 | .fntype => return self.writeInstToStreamGeneric(stream, .fntype, decl, inst_table), |
| 331 | .intcast => return self.writeInstToStreamGeneric(stream, .intcast, decl, inst_table), | |
| 318 | 332 | } |
| 319 | 333 | } |
| 320 | 334 |
src-self-hosted/type.zig+162| ... | ... | @@ -2,6 +2,7 @@ const std = @import("std"); |
| 2 | 2 | const Value = @import("value.zig").Value; |
| 3 | 3 | const assert = std.debug.assert; |
| 4 | 4 | const Allocator = std.mem.Allocator; |
| 5 | const Target = std.Target; | |
| 5 | 6 | |
| 6 | 7 | /// This is the raw data, with no bookkeeping, no memory awareness, no de-duplication. |
| 7 | 8 | /// It's important for this struct to be small. |
| ... | ... | @@ -333,6 +334,44 @@ pub const Type = extern union { |
| 333 | 334 | }; |
| 334 | 335 | } |
| 335 | 336 | |
| 337 | /// Asserts the type is a fixed-width integer. | |
| 338 | pub fn intInfo(self: Type, target: Target) struct { signed: bool, bits: u16 } { | |
| 339 | return switch (self.tag()) { | |
| 340 | .@"f16", | |
| 341 | .@"f32", | |
| 342 | .@"f64", | |
| 343 | .@"f128", | |
| 344 | .@"c_longdouble", | |
| 345 | .@"c_void", | |
| 346 | .@"bool", | |
| 347 | .@"void", | |
| 348 | .@"type", | |
| 349 | .@"anyerror", | |
| 350 | .@"comptime_int", | |
| 351 | .@"comptime_float", | |
| 352 | .@"noreturn", | |
| 353 | .fn_naked_noreturn_no_args, | |
| 354 | .array, | |
| 355 | .single_const_pointer, | |
| 356 | .array_u8_sentinel_0, | |
| 357 | .const_slice_u8, | |
| 358 | => unreachable, | |
| 359 | ||
| 360 | .@"u8" => .{ .signed = false, .bits = 8 }, | |
| 361 | .@"i8" => .{ .signed = true, .bits = 8 }, | |
| 362 | .@"usize" => .{ .signed = false, .bits = target.cpu.arch.ptrBitWidth() }, | |
| 363 | .@"isize" => .{ .signed = true, .bits = target.cpu.arch.ptrBitWidth() }, | |
| 364 | .@"c_short" => .{ .signed = true, .bits = CInteger.short.sizeInBits(target) }, | |
| 365 | .@"c_ushort" => .{ .signed = false, .bits = CInteger.ushort.sizeInBits(target) }, | |
| 366 | .@"c_int" => .{ .signed = true, .bits = CInteger.int.sizeInBits(target) }, | |
| 367 | .@"c_uint" => .{ .signed = false, .bits = CInteger.uint.sizeInBits(target) }, | |
| 368 | .@"c_long" => .{ .signed = true, .bits = CInteger.long.sizeInBits(target) }, | |
| 369 | .@"c_ulong" => .{ .signed = false, .bits = CInteger.ulong.sizeInBits(target) }, | |
| 370 | .@"c_longlong" => .{ .signed = true, .bits = CInteger.longlong.sizeInBits(target) }, | |
| 371 | .@"c_ulonglong" => .{ .signed = false, .bits = CInteger.ulonglong.sizeInBits(target) }, | |
| 372 | }; | |
| 373 | } | |
| 374 | ||
| 336 | 375 | /// This enum does not directly correspond to `std.builtin.TypeId` because |
| 337 | 376 | /// it has extra enum tags in it, as a way of using less memory. For example, |
| 338 | 377 | /// even though Zig recognizes `*align(10) i32` and `*i32` both as Pointer types |
| ... | ... | @@ -401,3 +440,126 @@ pub const Type = extern union { |
| 401 | 440 | }; |
| 402 | 441 | }; |
| 403 | 442 | }; |
| 443 | ||
| 444 | pub const CInteger = enum { | |
| 445 | short, | |
| 446 | ushort, | |
| 447 | int, | |
| 448 | uint, | |
| 449 | long, | |
| 450 | ulong, | |
| 451 | longlong, | |
| 452 | ulonglong, | |
| 453 | ||
| 454 | pub fn sizeInBits(self: CInteger, target: Target) u16 { | |
| 455 | const arch = target.cpu.arch; | |
| 456 | switch (target.os.tag) { | |
| 457 | .freestanding, .other => switch (target.cpu.arch) { | |
| 458 | .msp430 => switch (self) { | |
| 459 | .short, | |
| 460 | .ushort, | |
| 461 | .int, | |
| 462 | .uint, | |
| 463 | => return 16, | |
| 464 | .long, | |
| 465 | .ulong, | |
| 466 | => return 32, | |
| 467 | .longlong, | |
| 468 | .ulonglong, | |
| 469 | => return 64, | |
| 470 | }, | |
| 471 | else => switch (self) { | |
| 472 | .short, | |
| 473 | .ushort, | |
| 474 | => return 16, | |
| 475 | .int, | |
| 476 | .uint, | |
| 477 | => return 32, | |
| 478 | .long, | |
| 479 | .ulong, | |
| 480 | => return target.cpu.arch.ptrBitWidth(), | |
| 481 | .longlong, | |
| 482 | .ulonglong, | |
| 483 | => return 64, | |
| 484 | }, | |
| 485 | }, | |
| 486 | ||
| 487 | .linux, | |
| 488 | .macosx, | |
| 489 | .freebsd, | |
| 490 | .netbsd, | |
| 491 | .dragonfly, | |
| 492 | .openbsd, | |
| 493 | .wasi, | |
| 494 | .emscripten, | |
| 495 | => switch (self) { | |
| 496 | .short, | |
| 497 | .ushort, | |
| 498 | => return 16, | |
| 499 | .int, | |
| 500 | .uint, | |
| 501 | => return 32, | |
| 502 | .long, | |
| 503 | .ulong, | |
| 504 | => return target.cpu.arch.ptrBitWidth(), | |
| 505 | .longlong, | |
| 506 | .ulonglong, | |
| 507 | => return 64, | |
| 508 | }, | |
| 509 | ||
| 510 | .windows, .uefi => switch (self) { | |
| 511 | .short, | |
| 512 | .ushort, | |
| 513 | => return 16, | |
| 514 | .int, | |
| 515 | .uint, | |
| 516 | .long, | |
| 517 | .ulong, | |
| 518 | => return 32, | |
| 519 | .longlong, | |
| 520 | .ulonglong, | |
| 521 | => return 64, | |
| 522 | }, | |
| 523 | ||
| 524 | .ios => switch (self) { | |
| 525 | .short, | |
| 526 | .ushort, | |
| 527 | => return 16, | |
| 528 | .int, | |
| 529 | .uint, | |
| 530 | => return 32, | |
| 531 | .long, | |
| 532 | .ulong, | |
| 533 | .longlong, | |
| 534 | .ulonglong, | |
| 535 | => return 64, | |
| 536 | }, | |
| 537 | ||
| 538 | .ananas, | |
| 539 | .cloudabi, | |
| 540 | .fuchsia, | |
| 541 | .kfreebsd, | |
| 542 | .lv2, | |
| 543 | .solaris, | |
| 544 | .haiku, | |
| 545 | .minix, | |
| 546 | .rtems, | |
| 547 | .nacl, | |
| 548 | .cnk, | |
| 549 | .aix, | |
| 550 | .cuda, | |
| 551 | .nvcl, | |
| 552 | .amdhsa, | |
| 553 | .ps4, | |
| 554 | .elfiamcu, | |
| 555 | .tvos, | |
| 556 | .watchos, | |
| 557 | .mesa3d, | |
| 558 | .contiki, | |
| 559 | .amdpal, | |
| 560 | .hermit, | |
| 561 | .hurd, | |
| 562 | => @panic("TODO specify the C integer type sizes for this OS"), | |
| 563 | } | |
| 564 | } | |
| 565 | }; |
src-self-hosted/value.zig+73| ... | ... | @@ -3,6 +3,7 @@ const Type = @import("type.zig").Type; |
| 3 | 3 | const log2 = std.math.log2; |
| 4 | 4 | const assert = std.debug.assert; |
| 5 | 5 | const BigInt = std.math.big.Int; |
| 6 | const Target = std.Target; | |
| 6 | 7 | |
| 7 | 8 | /// This is the raw data, with no bookkeeping, no memory awareness, |
| 8 | 9 | /// no de-duplication, and no type system awareness. |
| ... | ... | @@ -198,6 +199,78 @@ pub const Value = extern union { |
| 198 | 199 | }; |
| 199 | 200 | } |
| 200 | 201 | |
| 202 | /// Asserts the value is an integer, and the destination type is ComptimeInt or Int. | |
| 203 | pub fn intFitsInType(self: Value, ty: Type, target: Target) bool { | |
| 204 | switch (self.tag()) { | |
| 205 | .ty, | |
| 206 | .u8_type, | |
| 207 | .i8_type, | |
| 208 | .isize_type, | |
| 209 | .usize_type, | |
| 210 | .c_short_type, | |
| 211 | .c_ushort_type, | |
| 212 | .c_int_type, | |
| 213 | .c_uint_type, | |
| 214 | .c_long_type, | |
| 215 | .c_ulong_type, | |
| 216 | .c_longlong_type, | |
| 217 | .c_ulonglong_type, | |
| 218 | .c_longdouble_type, | |
| 219 | .f16_type, | |
| 220 | .f32_type, | |
| 221 | .f64_type, | |
| 222 | .f128_type, | |
| 223 | .c_void_type, | |
| 224 | .bool_type, | |
| 225 | .void_type, | |
| 226 | .type_type, | |
| 227 | .anyerror_type, | |
| 228 | .comptime_int_type, | |
| 229 | .comptime_float_type, | |
| 230 | .noreturn_type, | |
| 231 | .fn_naked_noreturn_no_args_type, | |
| 232 | .const_slice_u8_type, | |
| 233 | .void_value, | |
| 234 | .noreturn_value, | |
| 235 | .bool_true, | |
| 236 | .bool_false, | |
| 237 | .function, | |
| 238 | .ref, | |
| 239 | .bytes, | |
| 240 | => unreachable, | |
| 241 | ||
| 242 | .int_u64 => switch (ty.zigTypeTag()) { | |
| 243 | .Int => { | |
| 244 | const x = self.cast(Payload.Int_u64).?.int; | |
| 245 | const info = ty.intInfo(target); | |
| 246 | const needed_bits = std.math.log2(x) + 1 + @boolToInt(info.signed); | |
| 247 | return info.bits >= needed_bits; | |
| 248 | }, | |
| 249 | .ComptimeInt => return true, | |
| 250 | else => unreachable, | |
| 251 | }, | |
| 252 | .int_i64 => switch (ty.zigTypeTag()) { | |
| 253 | .Int => { | |
| 254 | const x = self.cast(Payload.Int_i64).?.int; | |
| 255 | const info = ty.intInfo(target); | |
| 256 | if (!info.signed and x < 0) | |
| 257 | return false; | |
| 258 | @panic("TODO implement i64 intFitsInType"); | |
| 259 | }, | |
| 260 | .ComptimeInt => return true, | |
| 261 | else => unreachable, | |
| 262 | }, | |
| 263 | .int_big => switch (ty.zigTypeTag()) { | |
| 264 | .Int => { | |
| 265 | const info = ty.intInfo(target); | |
| 266 | return self.cast(Payload.IntBig).?.big_int.fitsInTwosComp(info.signed, info.bits); | |
| 267 | }, | |
| 268 | .ComptimeInt => return true, | |
| 269 | else => unreachable, | |
| 270 | }, | |
| 271 | } | |
| 272 | } | |
| 273 | ||
| 201 | 274 | /// This type is not copyable since it may contain pointers to its inner data. |
| 202 | 275 | pub const Payload = struct { |
| 203 | 276 | tag: Tag, |
src/ir.cpp+3-3| ... | ... | @@ -11289,9 +11289,9 @@ static bool ir_num_lit_fits_in_other_type(IrAnalyze *ira, IrInstGen *instruction |
| 11289 | 11289 | Buf *val_buf = buf_alloc(); |
| 11290 | 11290 | bigint_append_buf(val_buf, &const_val->data.x_bigint, 10); |
| 11291 | 11291 | ir_add_error_node(ira, instruction->base.source_node, |
| 11292 | buf_sprintf("integer value %s has no representation in type '%s'", | |
| 11293 | buf_ptr(val_buf), | |
| 11294 | buf_ptr(&other_type->name))); | |
| 11292 | buf_sprintf("type %s cannot represent integer value %s", | |
| 11293 | buf_ptr(&other_type->name), | |
| 11294 | buf_ptr(val_buf))); | |
| 11295 | 11295 | return false; |
| 11296 | 11296 | } |
| 11297 | 11297 | if (other_type->data.floating.bit_count >= const_val->type->data.floating.bit_count) { |