| ... | @@ -449,7 +449,7 @@ pub const Function = struct { | ... | @@ -449,7 +449,7 @@ pub const Function = struct { |
| 449 | } | 449 | } |
| 450 | | 450 | |
| 451 | fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) { | 451 | fn fmtIntLiteral(f: *Function, ty: Type, val: Value) !std.fmt.Formatter(formatIntLiteral) { |
| 452 | return f.object.dg.fmtIntLiteral(ty, val); | 452 | return f.object.dg.fmtIntLiteral(ty, val, .Other); |
| 453 | } | 453 | } |
| 454 | | 454 | |
| 455 | fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 { | 455 | fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 { |
| ... | @@ -574,9 +574,9 @@ pub const DeclGen = struct { | ... | @@ -574,9 +574,9 @@ pub const DeclGen = struct { |
| 574 | const len_val = Value.initPayload(&len_pl.base); | 574 | const len_val = Value.initPayload(&len_pl.base); |
| 575 | | 575 | |
| 576 | if (location == .StaticInitializer) { | 576 | if (location == .StaticInitializer) { |
| 577 | return writer.print(", {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)}); | 577 | return writer.print(", {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val, .Other)}); |
| 578 | } else { | 578 | } else { |
| 579 | return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val)}); | 579 | return writer.print(", .len = {} }}", .{try dg.fmtIntLiteral(Type.usize, len_val, .Other)}); |
| 580 | } | 580 | } |
| 581 | } | 581 | } |
| 582 | | 582 | |
| ... | @@ -606,7 +606,7 @@ pub const DeclGen = struct { | ... | @@ -606,7 +606,7 @@ pub const DeclGen = struct { |
| 606 | try writer.writeByte(')'); | 606 | try writer.writeByte(')'); |
| 607 | } | 607 | } |
| 608 | switch (ptr_val.tag()) { | 608 | switch (ptr_val.tag()) { |
| 609 | .int_u64, .one => try writer.print("{x}", .{try dg.fmtIntLiteral(Type.usize, ptr_val)}), | 609 | .int_u64, .one => try writer.print("{x}", .{try dg.fmtIntLiteral(Type.usize, ptr_val, .Other)}), |
| 610 | .decl_ref_mut, .decl_ref, .variable => { | 610 | .decl_ref_mut, .decl_ref, .variable => { |
| 611 | const decl_index = switch (ptr_val.tag()) { | 611 | const decl_index = switch (ptr_val.tag()) { |
| 612 | .decl_ref => ptr_val.castTag(.decl_ref).?.data, | 612 | .decl_ref => ptr_val.castTag(.decl_ref).?.data, |
| ... | @@ -670,7 +670,9 @@ pub const DeclGen = struct { | ... | @@ -670,7 +670,9 @@ pub const DeclGen = struct { |
| 670 | container_ptr_ty, | 670 | container_ptr_ty, |
| 671 | location, | 671 | location, |
| 672 | ); | 672 | ); |
| 673 | try writer.print(" + {})", .{try dg.fmtIntLiteral(Type.usize, byte_offset_val)}); | 673 | try writer.print(" + {})", .{ |
| | 674 | try dg.fmtIntLiteral(Type.usize, byte_offset_val, .Other), |
| | 675 | }); |
| 674 | }, | 676 | }, |
| 675 | .end => { | 677 | .end => { |
| 676 | try writer.writeAll("(("); | 678 | try writer.writeAll("(("); |
| ... | @@ -680,7 +682,9 @@ pub const DeclGen = struct { | ... | @@ -680,7 +682,9 @@ pub const DeclGen = struct { |
| 680 | container_ptr_ty, | 682 | container_ptr_ty, |
| 681 | location, | 683 | location, |
| 682 | ); | 684 | ); |
| 683 | try writer.print(") + {})", .{try dg.fmtIntLiteral(Type.usize, Value.one)}); | 685 | try writer.print(") + {})", .{ |
| | 686 | try dg.fmtIntLiteral(Type.usize, Value.one, .Other), |
| | 687 | }); |
| 684 | }, | 688 | }, |
| 685 | } | 689 | } |
| 686 | }, | 690 | }, |
| ... | @@ -746,7 +750,7 @@ pub const DeclGen = struct { | ... | @@ -746,7 +750,7 @@ pub const DeclGen = struct { |
| 746 | return writer.writeAll("false"); | 750 | return writer.writeAll("false"); |
| 747 | } | 751 | } |
| 748 | }, | 752 | }, |
| 749 | .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteralLoc(ty, val, location)}), | 753 | .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val, location)}), |
| 750 | .Float => { | 754 | .Float => { |
| 751 | const bits = ty.floatBits(target); | 755 | const bits = ty.floatBits(target); |
| 752 | var int_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits }; | 756 | var int_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits }; |
| ... | @@ -780,11 +784,11 @@ pub const DeclGen = struct { | ... | @@ -780,11 +784,11 @@ pub const DeclGen = struct { |
| 780 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 784 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 781 | const ptr_ty = ty.slicePtrFieldType(&buf); | 785 | const ptr_ty = ty.slicePtrFieldType(&buf); |
| 782 | try dg.renderType(writer, ptr_ty); | 786 | try dg.renderType(writer, ptr_ty); |
| 783 | return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val)}); | 787 | return writer.print("){x}, {0x}}}", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); |
| 784 | } else { | 788 | } else { |
| 785 | try writer.writeAll("(("); | 789 | try writer.writeAll("(("); |
| 786 | try dg.renderType(writer, ty); | 790 | try dg.renderType(writer, ty); |
| 787 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)}); | 791 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); |
| 788 | }, | 792 | }, |
| 789 | .Optional => { | 793 | .Optional => { |
| 790 | var opt_buf: Type.Payload.ElemType = undefined; | 794 | var opt_buf: Type.Payload.ElemType = undefined; |
| ... | @@ -831,7 +835,7 @@ pub const DeclGen = struct { | ... | @@ -831,7 +835,7 @@ pub const DeclGen = struct { |
| 831 | | 835 | |
| 832 | return writer.writeByte('}'); | 836 | return writer.writeByte('}'); |
| 833 | }, | 837 | }, |
| 834 | .Packed => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef)}), | 838 | .Packed => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef, .Other)}), |
| 835 | }, | 839 | }, |
| 836 | .Union => { | 840 | .Union => { |
| 837 | if (!location.isInitializer()) { | 841 | if (!location.isInitializer()) { |
| ... | @@ -854,7 +858,7 @@ pub const DeclGen = struct { | ... | @@ -854,7 +858,7 @@ pub const DeclGen = struct { |
| 854 | if (!field.ty.hasRuntimeBits()) continue; | 858 | if (!field.ty.hasRuntimeBits()) continue; |
| 855 | try dg.renderValue(writer, field.ty, val, initializer_type); | 859 | try dg.renderValue(writer, field.ty, val, initializer_type); |
| 856 | break; | 860 | break; |
| 857 | } else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)}); | 861 | } else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef, .Other)}); |
| 858 | if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}'); | 862 | if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}'); |
| 859 | return writer.writeByte('}'); | 863 | return writer.writeByte('}'); |
| 860 | }, | 864 | }, |
| ... | @@ -868,7 +872,7 @@ pub const DeclGen = struct { | ... | @@ -868,7 +872,7 @@ pub const DeclGen = struct { |
| 868 | try writer.writeAll("{ .payload = "); | 872 | try writer.writeAll("{ .payload = "); |
| 869 | try dg.renderValue(writer, ty.errorUnionPayload(), val, initializer_type); | 873 | try dg.renderValue(writer, ty.errorUnionPayload(), val, initializer_type); |
| 870 | return writer.print(", .error = {x} }}", .{ | 874 | return writer.print(", .error = {x} }}", .{ |
| 871 | try dg.fmtIntLiteral(ty.errorUnionSet(), val), | 875 | try dg.fmtIntLiteral(ty.errorUnionSet(), val, .Other), |
| 872 | }); | 876 | }); |
| 873 | }, | 877 | }, |
| 874 | .Array, .Vector => { | 878 | .Array, .Vector => { |
| ... | @@ -927,7 +931,7 @@ pub const DeclGen = struct { | ... | @@ -927,7 +931,7 @@ pub const DeclGen = struct { |
| 927 | .decl_ref_mut, | 931 | .decl_ref_mut, |
| 928 | .decl_ref, | 932 | .decl_ref, |
| 929 | => try dg.renderParentPtr(writer, val, ty, location), | 933 | => try dg.renderParentPtr(writer, val, ty, location), |
| 930 | else => try writer.print("{}", .{try dg.fmtIntLiteralLoc(ty, val, location)}), | 934 | else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val, location)}), |
| 931 | }, | 935 | }, |
| 932 | .Float => { | 936 | .Float => { |
| 933 | const bits = ty.floatBits(target); | 937 | const bits = ty.floatBits(target); |
| ... | @@ -1020,7 +1024,7 @@ pub const DeclGen = struct { | ... | @@ -1020,7 +1024,7 @@ pub const DeclGen = struct { |
| 1020 | try writer.writeAll(", "); | 1024 | try writer.writeAll(", "); |
| 1021 | empty = false; | 1025 | empty = false; |
| 1022 | } | 1026 | } |
| 1023 | try writer.print("{x}", .{try dg.fmtIntLiteralLoc(int_ty, int_val, location)}); | 1027 | try writer.print("{x}", .{try dg.fmtIntLiteral(int_ty, int_val, location)}); |
| 1024 | if (!empty) try writer.writeByte(')'); | 1028 | if (!empty) try writer.writeByte(')'); |
| 1025 | return; | 1029 | return; |
| 1026 | }, | 1030 | }, |
| ... | @@ -1069,7 +1073,7 @@ pub const DeclGen = struct { | ... | @@ -1069,7 +1073,7 @@ pub const DeclGen = struct { |
| 1069 | .int_u64, .one => { | 1073 | .int_u64, .one => { |
| 1070 | try writer.writeAll("(("); | 1074 | try writer.writeAll("(("); |
| 1071 | try dg.renderType(writer, ty); | 1075 | try dg.renderType(writer, ty); |
| 1072 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val)}); | 1076 | return writer.print("){x})", .{try dg.fmtIntLiteral(Type.usize, val, .Other)}); |
| 1073 | }, | 1077 | }, |
| 1074 | .field_ptr, | 1078 | .field_ptr, |
| 1075 | .elem_ptr, | 1079 | .elem_ptr, |
| ... | @@ -1889,11 +1893,11 @@ pub const DeclGen = struct { | ... | @@ -1889,11 +1893,11 @@ pub const DeclGen = struct { |
| 1889 | const int_info = ty.intInfo(target); | 1893 | const int_info = ty.intInfo(target); |
| 1890 | if (int_info.signedness == .signed) { | 1894 | if (int_info.signedness == .signed) { |
| 1891 | const min_val = try ty.minInt(stack.get(), target); | 1895 | const min_val = try ty.minInt(stack.get(), target); |
| 1892 | try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, min_val)}); | 1896 | try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, min_val, .Other)}); |
| 1893 | } | 1897 | } |
| 1894 | | 1898 | |
| 1895 | const max_val = try ty.maxInt(stack.get(), target); | 1899 | const max_val = try ty.maxInt(stack.get(), target); |
| 1896 | try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, max_val)}); | 1900 | try writer.print(", {x}", .{try dg.fmtIntLiteral(ty, max_val, .Other)}); |
| 1897 | }, | 1901 | }, |
| 1898 | .Bits => { | 1902 | .Bits => { |
| 1899 | var bits_pl = Value.Payload.U64{ | 1903 | var bits_pl = Value.Payload.U64{ |
| ... | @@ -1901,7 +1905,7 @@ pub const DeclGen = struct { | ... | @@ -1901,7 +1905,7 @@ pub const DeclGen = struct { |
| 1901 | .data = ty.bitSize(target), | 1905 | .data = ty.bitSize(target), |
| 1902 | }; | 1906 | }; |
| 1903 | const bits_val = Value.initPayload(&bits_pl.base); | 1907 | const bits_val = Value.initPayload(&bits_pl.base); |
| 1904 | try writer.print(", {}", .{try dg.fmtIntLiteral(Type.u8, bits_val)}); | 1908 | try writer.print(", {}", .{try dg.fmtIntLiteral(Type.u8, bits_val, .Other)}); |
| 1905 | }, | 1909 | }, |
| 1906 | } | 1910 | } |
| 1907 | } | 1911 | } |
| ... | @@ -1910,30 +1914,21 @@ pub const DeclGen = struct { | ... | @@ -1910,30 +1914,21 @@ pub const DeclGen = struct { |
| 1910 | dg: *DeclGen, | 1914 | dg: *DeclGen, |
| 1911 | ty: Type, | 1915 | ty: Type, |
| 1912 | val: Value, | 1916 | val: Value, |
| | 1917 | loc: ValueRenderLocation, |
| 1913 | ) !std.fmt.Formatter(formatIntLiteral) { | 1918 | ) !std.fmt.Formatter(formatIntLiteral) { |
| 1914 | const int_info = ty.intInfo(dg.module.getTarget()); | 1919 | const kind: CType.Kind = switch (loc) { |
| 1915 | const c_bits = toCIntBits(int_info.bits); | 1920 | .FunctionArgument => .parameter, |
| 1916 | if (c_bits == null or c_bits.? > 128) | 1921 | .Initializer, .Other => .complete, |
| 1917 | return dg.fail("TODO implement integer constants larger than 128 bits", .{}); | 1922 | .StaticInitializer => .global, |
| | 1923 | }; |
| 1918 | return std.fmt.Formatter(formatIntLiteral){ .data = .{ | 1924 | return std.fmt.Formatter(formatIntLiteral){ .data = .{ |
| 1919 | .ty = ty, | 1925 | .dg = dg, |
| | 1926 | .int_info = ty.intInfo(dg.module.getTarget()), |
| | 1927 | .kind = kind, |
| | 1928 | .cty = try dg.typeToCType(ty, kind), |
| 1920 | .val = val, | 1929 | .val = val, |
| 1921 | .mod = dg.module, | | |
| 1922 | } }; | 1930 | } }; |
| 1923 | } | 1931 | } |
| 1924 | | | |
| 1925 | fn fmtIntLiteralLoc( | | |
| 1926 | dg: *DeclGen, | | |
| 1927 | ty: Type, | | |
| 1928 | val: Value, | | |
| 1929 | location: ValueRenderLocation, // TODO: Instead add this as optional arg to fmtIntLiteral | | |
| 1930 | ) !std.fmt.Formatter(formatIntLiteral) { | | |
| 1931 | const int_info = ty.intInfo(dg.module.getTarget()); | | |
| 1932 | const c_bits = toCIntBits(int_info.bits); | | |
| 1933 | if (c_bits == null or c_bits.? > 128) | | |
| 1934 | return dg.fail("TODO implement integer constants larger than 128 bits", .{}); | | |
| 1935 | return std.fmt.Formatter(formatIntLiteral){ .data = .{ .ty = ty, .val = val, .mod = dg.module, .location = location } }; | | |
| 1936 | } | | |
| 1937 | }; | 1932 | }; |
| 1938 | | 1933 | |
| 1939 | const CTypeFix = enum { prefix, suffix }; | 1934 | const CTypeFix = enum { prefix, suffix }; |
| ... | @@ -2450,7 +2445,7 @@ pub fn genErrDecls(o: *Object) !void { | ... | @@ -2450,7 +2445,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 2450 | const len_val = Value.initPayload(&len_pl.base); | 2445 | const len_val = Value.initPayload(&len_pl.base); |
| 2451 | | 2446 | |
| 2452 | try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{ | 2447 | try writer.print("{{" ++ name_prefix ++ "{}, {}}}", .{ |
| 2453 | fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val), | 2448 | fmtIdent(name), try o.dg.fmtIntLiteral(Type.usize, len_val, .Other), |
| 2454 | }); | 2449 | }); |
| 2455 | } | 2450 | } |
| 2456 | try writer.writeAll("};\n"); | 2451 | try writer.writeAll("};\n"); |
| ... | @@ -2501,7 +2496,10 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | ... | @@ -2501,7 +2496,10 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2501 | var int_pl: Value.Payload.U64 = undefined; | 2496 | var int_pl: Value.Payload.U64 = undefined; |
| 2502 | const int_val = tag_val.enumToInt(enum_ty, &int_pl); | 2497 | const int_val = tag_val.enumToInt(enum_ty, &int_pl); |
| 2503 | | 2498 | |
| 2504 | var name_ty_pl = Type.Payload.Len{ .base = .{ .tag = .array_u8_sentinel_0 }, .data = name.len }; | 2499 | var name_ty_pl = Type.Payload.Len{ |
| | 2500 | .base = .{ .tag = .array_u8_sentinel_0 }, |
| | 2501 | .data = name.len, |
| | 2502 | }; |
| 2505 | const name_ty = Type.initPayload(&name_ty_pl.base); | 2503 | const name_ty = Type.initPayload(&name_ty_pl.base); |
| 2506 | | 2504 | |
| 2507 | var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name }; | 2505 | var name_pl = Value.Payload.Bytes{ .base = .{ .tag = .bytes }, .data = name }; |
| ... | @@ -2510,14 +2508,16 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | ... | @@ -2510,14 +2508,16 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2510 | var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; | 2508 | var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; |
| 2511 | const len_val = Value.initPayload(&len_pl.base); | 2509 | const len_val = Value.initPayload(&len_pl.base); |
| 2512 | | 2510 | |
| 2513 | try w.print(" case {}: {{\n static ", .{try o.dg.fmtIntLiteral(enum_ty, int_val)}); | 2511 | try w.print(" case {}: {{\n static ", .{ |
| | 2512 | try o.dg.fmtIntLiteral(enum_ty, int_val, .Other), |
| | 2513 | }); |
| 2514 | try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, 0, .complete); | 2514 | try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, 0, .complete); |
| 2515 | try w.writeAll(" = "); | 2515 | try w.writeAll(" = "); |
| 2516 | try o.dg.renderValue(w, name_ty, name_val, .Initializer); | 2516 | try o.dg.renderValue(w, name_ty, name_val, .Initializer); |
| 2517 | try w.writeAll(";\n return ("); | 2517 | try w.writeAll(";\n return ("); |
| 2518 | try o.dg.renderType(w, name_slice_ty); | 2518 | try o.dg.renderType(w, name_slice_ty); |
| 2519 | try w.print("){{{}, {}}};\n", .{ | 2519 | try w.print("){{{}, {}}};\n", .{ |
| 2520 | fmtIdent("name"), try o.dg.fmtIntLiteral(Type.usize, len_val), | 2520 | fmtIdent("name"), try o.dg.fmtIntLiteral(Type.usize, len_val, .Other), |
| 2521 | }); | 2521 | }); |
| 2522 | | 2522 | |
| 2523 | try w.writeAll(" }\n"); | 2523 | try w.writeAll(" }\n"); |
| ... | @@ -2535,7 +2535,12 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { | ... | @@ -2535,7 +2535,12 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2535 | | 2535 | |
| 2536 | const fwd_decl_writer = o.dg.fwd_decl.writer(); | 2536 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2537 | try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)}); | 2537 | try fwd_decl_writer.print("static zig_{s} ", .{@tagName(key)}); |
| 2538 | try o.dg.renderFunctionSignature(fwd_decl_writer, fn_decl_index, .forward, .{ .string = fn_name }); | 2538 | try o.dg.renderFunctionSignature( |
| | 2539 | fwd_decl_writer, |
| | 2540 | fn_decl_index, |
| | 2541 | .forward, |
| | 2542 | .{ .string = fn_name }, |
| | 2543 | ); |
| 2539 | try fwd_decl_writer.writeAll(";\n"); | 2544 | try fwd_decl_writer.writeAll(";\n"); |
| 2540 | | 2545 | |
| 2541 | try w.print("static zig_{s} ", .{@tagName(key)}); | 2546 | try w.print("static zig_{s} ", .{@tagName(key)}); |
| ... | @@ -7177,30 +7182,33 @@ fn undefPattern(comptime IntType: type) IntType { | ... | @@ -7177,30 +7182,33 @@ fn undefPattern(comptime IntType: type) IntType { |
| 7177 | return @bitCast(IntType, @as(UnsignedType, (1 << (int_info.bits | 1)) / 3)); | 7182 | return @bitCast(IntType, @as(UnsignedType, (1 << (int_info.bits | 1)) / 3)); |
| 7178 | } | 7183 | } |
| 7179 | | 7184 | |
| 7180 | const FormatIntLiteralContext = struct { ty: Type, val: Value, mod: *Module, location: ?ValueRenderLocation = null }; | 7185 | const FormatIntLiteralContext = struct { |
| | 7186 | dg: *DeclGen, |
| | 7187 | int_info: std.builtin.Type.Int, |
| | 7188 | kind: CType.Kind, |
| | 7189 | cty: CType, |
| | 7190 | val: Value, |
| | 7191 | }; |
| 7181 | fn formatIntLiteral( | 7192 | fn formatIntLiteral( |
| 7182 | data: FormatIntLiteralContext, | 7193 | data: FormatIntLiteralContext, |
| 7183 | comptime fmt: []const u8, | 7194 | comptime fmt: []const u8, |
| 7184 | options: std.fmt.FormatOptions, | 7195 | options: std.fmt.FormatOptions, |
| 7185 | writer: anytype, | 7196 | writer: anytype, |
| 7186 | ) @TypeOf(writer).Error!void { | 7197 | ) @TypeOf(writer).Error!void { |
| 7187 | const target = data.mod.getTarget(); | 7198 | const target = data.dg.module.getTarget(); |
| 7188 | const int_info = data.ty.intInfo(target); | | |
| 7189 | | 7199 | |
| 7190 | const ExpectedContents = struct { | 7200 | const ExpectedContents = struct { |
| 7191 | const base = 10; | 7201 | const base = 10; |
| 7192 | const limbs_count_128 = BigInt.calcTwosCompLimbCount(128); | 7202 | const bits = 128; |
| 7193 | const expected_needed_limbs_count = BigInt.calcToStringLimbsBufferLen(limbs_count_128, base); | 7203 | const limbs_count = BigInt.calcTwosCompLimbCount(bits); |
| 7194 | const worst_case_int = BigInt.Const{ | | |
| 7195 | .limbs = &([1]BigIntLimb{std.math.maxInt(BigIntLimb)} ** expected_needed_limbs_count), | | |
| 7196 | .positive = false, | | |
| 7197 | }; | | |
| 7198 | | 7204 | |
| 7199 | undef_limbs: [limbs_count_128]BigIntLimb, | 7205 | undef_limbs: [limbs_count]BigIntLimb, |
| 7200 | wrap_limbs: [limbs_count_128]BigIntLimb, | 7206 | wrap_limbs: [limbs_count]BigIntLimb, |
| | 7207 | to_string_buf: [bits]u8, |
| | 7208 | to_string_limbs: [BigInt.calcToStringLimbsBufferLen(limbs_count, base)]BigIntLimb, |
| 7201 | }; | 7209 | }; |
| 7202 | var stack align(@alignOf(ExpectedContents)) = | 7210 | var stack align(@alignOf(ExpectedContents)) = |
| 7203 | std.heap.stackFallback(@sizeOf(ExpectedContents), data.mod.gpa); | 7211 | std.heap.stackFallback(@sizeOf(ExpectedContents), data.dg.gpa); |
| 7204 | const allocator = stack.get(); | 7212 | const allocator = stack.get(); |
| 7205 | | 7213 | |
| 7206 | var undef_limbs: []BigIntLimb = &.{}; | 7214 | var undef_limbs: []BigIntLimb = &.{}; |
| ... | @@ -7208,7 +7216,7 @@ fn formatIntLiteral( | ... | @@ -7208,7 +7216,7 @@ fn formatIntLiteral( |
| 7208 | | 7216 | |
| 7209 | var int_buf: Value.BigIntSpace = undefined; | 7217 | var int_buf: Value.BigIntSpace = undefined; |
| 7210 | const int = if (data.val.isUndefDeep()) blk: { | 7218 | const int = if (data.val.isUndefDeep()) blk: { |
| 7211 | undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(int_info.bits)); | 7219 | undef_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(data.int_info.bits)); |
| 7212 | std.mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb)); | 7220 | std.mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb)); |
| 7213 | | 7221 | |
| 7214 | var undef_int = BigInt.Mutable{ | 7222 | var undef_int = BigInt.Mutable{ |
| ... | @@ -7216,163 +7224,150 @@ fn formatIntLiteral( | ... | @@ -7216,163 +7224,150 @@ fn formatIntLiteral( |
| 7216 | .len = undef_limbs.len, | 7224 | .len = undef_limbs.len, |
| 7217 | .positive = true, | 7225 | .positive = true, |
| 7218 | }; | 7226 | }; |
| 7219 | undef_int.truncate(undef_int.toConst(), int_info.signedness, int_info.bits); | 7227 | undef_int.truncate(undef_int.toConst(), data.int_info.signedness, data.int_info.bits); |
| 7220 | break :blk undef_int.toConst(); | 7228 | break :blk undef_int.toConst(); |
| 7221 | } else data.val.toBigInt(&int_buf, target); | 7229 | } else data.val.toBigInt(&int_buf, target); |
| 7222 | assert(int.fitsInTwosComp(int_info.signedness, int_info.bits)); | 7230 | assert(int.fitsInTwosComp(data.int_info.signedness, data.int_info.bits)); |
| 7223 | | 7231 | |
| 7224 | const c_bits = toCIntBits(int_info.bits) orelse unreachable; | 7232 | const c_bits = @intCast(usize, data.cty.byteSize(data.dg.ctypes.set, target) * 8); |
| 7225 | var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; | 7233 | var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; |
| 7226 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); | 7234 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); |
| 7227 | | 7235 | |
| 7228 | const wrap_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)); | 7236 | var wrap = BigInt.Mutable{ |
| 7229 | defer allocator.free(wrap_limbs); | 7237 | .limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)), |
| 7230 | var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined }; | 7238 | .len = undefined, |
| 7231 | if (wrap.addWrap(int, one, int_info.signedness, c_bits) or | 7239 | .positive = undefined, |
| 7232 | int_info.signedness == .signed and wrap.subWrap(int, one, int_info.signedness, c_bits)) | 7240 | }; |
| 7233 | { | 7241 | defer allocator.free(wrap.limbs); |
| 7234 | const abbrev = switch (data.ty.tag()) { | 7242 | if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or |
| 7235 | .c_short, .c_ushort => "SHRT", | 7243 | data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) |
| 7236 | .c_int, .c_uint => "INT", | 7244 | return writer.print("{s}_{s}", .{ |
| 7237 | .c_long, .c_ulong => "LONG", | 7245 | data.cty.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{ |
| 7238 | .c_longlong, .c_ulonglong => "LLONG", | 7246 | if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, |
| 7239 | .isize, .usize => "INTPTR", | | |
| 7240 | else => return writer.print("zig_{s}Int_{c}{d}", .{ | | |
| 7241 | if (int.positive) "max" else "min", signAbbrev(int_info.signedness), c_bits, | | |
| 7242 | }), | 7247 | }), |
| 7243 | }; | 7248 | if (int.positive) "MAX" else "MIN", |
| 7244 | if (int_info.signedness == .unsigned) try writer.writeByte('U'); | 7249 | }); |
| 7245 | return writer.print("{s}_{s}", .{ abbrev, if (int.positive) "MAX" else "MIN" }); | | |
| 7246 | } | | |
| 7247 | | | |
| 7248 | var use_twos_comp = false; | | |
| 7249 | if (!int.positive) { | | |
| 7250 | if (c_bits > 64) { | | |
| 7251 | // TODO: Can this be done for decimal literals as well? | | |
| 7252 | if (fmt.len == 1 and fmt[0] != 'd') { | | |
| 7253 | use_twos_comp = true; | | |
| 7254 | } else { | | |
| 7255 | // TODO: Use fmtIntLiteral for 0? | | |
| 7256 | try writer.print("zig_sub_{c}{d}(zig_make_{c}{d}(0, 0), ", .{ signAbbrev(int_info.signedness), c_bits, signAbbrev(int_info.signedness), c_bits }); | | |
| 7257 | } | | |
| 7258 | } else { | | |
| 7259 | try writer.writeByte('-'); | | |
| 7260 | } | | |
| 7261 | } | | |
| 7262 | | 7250 | |
| 7263 | switch (data.ty.tag()) { | 7251 | const c_limb_info: struct { |
| 7264 | .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {}, | 7252 | cty: CType, |
| 7265 | else => { | 7253 | count: usize, |
| 7266 | if (int_info.bits <= 64) { | 7254 | endian: std.builtin.Endian, |
| 7267 | try writer.print("{s}INT{d}_C(", .{ switch (int_info.signedness) { | 7255 | homogeneous: bool, |
| 7268 | .signed => "", | 7256 | } = switch (data.cty.tag()) { |
| 7269 | .unsigned => "U", | 7257 | else => .{ |
| 7270 | }, c_bits }); | 7258 | .cty = CType.initTag(.void), |
| 7271 | } else if (data.location != null and data.location.? == .StaticInitializer) { | 7259 | .count = 1, |
| 7272 | // MSVC treats casting the struct initializer as not constant (C2099), so an alternate form is used in global initializers | 7260 | .endian = .Little, |
| 7273 | try writer.print("zig_make_constant_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }); | 7261 | .homogeneous = true, |
| 7274 | } else { | | |
| 7275 | try writer.print("zig_make_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }); | | |
| 7276 | } | | |
| 7277 | }, | 7262 | }, |
| 7278 | } | 7263 | .zig_u128, .zig_i128 => .{ |
| | 7264 | .cty = CType.initTag(.uint64_t), |
| | 7265 | .count = 2, |
| | 7266 | .endian = .Big, |
| | 7267 | .homogeneous = false, |
| | 7268 | }, |
| | 7269 | .array => info: { |
| | 7270 | const array_data = data.cty.castTag(.array).?.data; |
| | 7271 | break :info .{ |
| | 7272 | .cty = data.dg.indexToCType(array_data.elem_type), |
| | 7273 | .count = @intCast(usize, array_data.len), |
| | 7274 | .endian = target.cpu.arch.endian(), |
| | 7275 | .homogeneous = true, |
| | 7276 | }; |
| | 7277 | }, |
| | 7278 | }; |
| | 7279 | if (c_limb_info.count == 1) { |
| | 7280 | if (!int.positive) try writer.writeByte('-'); |
| | 7281 | try data.cty.renderLiteralPrefix(writer, data.kind); |
| 7279 | | 7282 | |
| 7280 | const limbs_count_64 = @divExact(64, @bitSizeOf(BigIntLimb)); | 7283 | const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) { |
| 7281 | if (c_bits <= 64) { | 7284 | 0 => .{ .base = 10 }, |
| 7282 | var base: u8 = undefined; | | |
| 7283 | var case: std.fmt.Case = undefined; | | |
| 7284 | switch (fmt.len) { | | |
| 7285 | 0 => base = 10, | | |
| 7286 | 1 => switch (fmt[0]) { | 7285 | 1 => switch (fmt[0]) { |
| 7287 | 'b' => { | 7286 | 'b' => style: { |
| 7288 | base = 2; | | |
| 7289 | try writer.writeAll("0b"); | 7287 | try writer.writeAll("0b"); |
| | 7288 | break :style .{ .base = 2 }; |
| 7290 | }, | 7289 | }, |
| 7291 | 'o' => { | 7290 | 'o' => style: { |
| 7292 | base = 8; | | |
| 7293 | try writer.writeByte('0'); | 7291 | try writer.writeByte('0'); |
| | 7292 | break :style .{ .base = 8 }; |
| 7294 | }, | 7293 | }, |
| 7295 | 'd' => base = 10, | 7294 | 'd' => .{ .base = 10 }, |
| 7296 | 'x' => { | 7295 | 'x', 'X' => |base| style: { |
| 7297 | base = 16; | | |
| 7298 | case = .lower; | | |
| 7299 | try writer.writeAll("0x"); | | |
| 7300 | }, | | |
| 7301 | 'X' => { | | |
| 7302 | base = 16; | | |
| 7303 | case = .upper; | | |
| 7304 | try writer.writeAll("0x"); | 7296 | try writer.writeAll("0x"); |
| | 7297 | break :style .{ .base = 16, .case = switch (base) { |
| | 7298 | 'x' => .lower, |
| | 7299 | 'X' => .upper, |
| | 7300 | else => unreachable, |
| | 7301 | } }; |
| 7305 | }, | 7302 | }, |
| 7306 | else => @compileError("Invalid fmt: " ++ fmt), | 7303 | else => @compileError("Invalid fmt: " ++ fmt), |
| 7307 | }, | 7304 | }, |
| 7308 | else => @compileError("Invalid fmt: " ++ fmt), | 7305 | else => @compileError("Invalid fmt: " ++ fmt), |
| 7309 | } | 7306 | }; |
| 7310 | | 7307 | |
| 7311 | var str: [64]u8 = undefined; | 7308 | const string = try int.abs().toStringAlloc(allocator, style.base, style.case); |
| 7312 | var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]BigIntLimb = undefined; | 7309 | defer allocator.free(string); |
| 7313 | try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]); | 7310 | try writer.writeAll(string); |
| 7314 | } else { | 7311 | } else { |
| 7315 | assert(c_bits == 128); | 7312 | try data.cty.renderLiteralPrefix(writer, data.kind); |
| 7316 | const split = std.math.min(int.limbs.len, limbs_count_64); | 7313 | wrap.convertToTwosComplement(int, .unsigned, data.int_info.bits); |
| 7317 | var twos_comp_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; | 7314 | std.mem.set(BigIntLimb, wrap.limbs[wrap.len..], 0); |
| 7318 | | 7315 | wrap.len = wrap.limbs.len; |
| 7319 | // Adding a negation in the C code before the doesn't work in all cases: | 7316 | const limbs_per_c_limb = @divExact(wrap.len, c_limb_info.count); |
| 7320 | // - struct versions would require an extra zig_sub_ call to negate, which wouldn't work in constant expressions | 7317 | |
| 7321 | // - negating the f80 int representation (i128) doesn't make sense | 7318 | var c_limb_int_info = std.builtin.Type.Int{ |
| 7322 | // Instead we write out the literal as a negative number in twos complement | 7319 | .signedness = undefined, |
| 7323 | var limbs = int.limbs; | 7320 | .bits = @intCast(u16, @divExact(c_bits, c_limb_info.count)), |
| 7324 | | 7321 | }; |
| 7325 | if (use_twos_comp) { | 7322 | var c_limb_cty: CType = undefined; |
| 7326 | var twos_comp = BigInt.Mutable{ | 7323 | |
| 7327 | .limbs = &twos_comp_limbs, | 7324 | var limb_offset: usize = 0; |
| 7328 | .positive = undefined, | 7325 | const most_significant_limb_i = wrap.len - limbs_per_c_limb; |
| | 7326 | while (limb_offset < wrap.len) : (limb_offset += limbs_per_c_limb) { |
| | 7327 | const limb_i = switch (c_limb_info.endian) { |
| | 7328 | .Little => limb_offset, |
| | 7329 | .Big => most_significant_limb_i - limb_offset, |
| | 7330 | }; |
| | 7331 | var c_limb_mut = BigInt.Mutable{ |
| | 7332 | .limbs = wrap.limbs[limb_i..][0..limbs_per_c_limb], |
| 7329 | .len = undefined, | 7333 | .len = undefined, |
| | 7334 | .positive = true, |
| 7330 | }; | 7335 | }; |
| | 7336 | c_limb_mut.normalize(limbs_per_c_limb); |
| 7331 | | 7337 | |
| 7332 | twos_comp.convertToTwosComplement(int, .signed, int_info.bits); | 7338 | if (limb_i == most_significant_limb_i and |
| 7333 | limbs = twos_comp.limbs; | 7339 | !c_limb_info.homogeneous and data.int_info.signedness == .signed) |
| 7334 | } | 7340 | { |
| 7335 | | 7341 | // most significant limb is actually signed |
| 7336 | var upper_pl = Value.Payload.BigInt{ | 7342 | c_limb_int_info.signedness = .signed; |
| 7337 | .base = .{ .tag = .int_big_positive }, | 7343 | c_limb_cty = c_limb_info.cty.toSigned(); |
| 7338 | .data = limbs[split..], | 7344 | |
| 7339 | }; | 7345 | c_limb_mut.positive = wrap.positive; |
| 7340 | const upper_val = Value.initPayload(&upper_pl.base); | 7346 | c_limb_mut.convertToTwosComplement( |
| 7341 | try formatIntLiteral(.{ | 7347 | c_limb_mut.toConst(), |
| 7342 | .ty = switch (int_info.signedness) { | 7348 | .signed, |
| 7343 | .unsigned => Type.u64, | 7349 | data.int_info.bits - limb_i * @bitSizeOf(BigIntLimb), |
| 7344 | .signed => if (use_twos_comp) Type.u64 else Type.i64, | 7350 | ); |
| 7345 | }, | 7351 | } else { |
| 7346 | .val = upper_val, | 7352 | c_limb_int_info.signedness = .unsigned; |
| 7347 | .mod = data.mod, | 7353 | c_limb_cty = c_limb_info.cty; |
| 7348 | }, fmt, options, writer); | 7354 | } |
| 7349 | | 7355 | var c_limb_val_pl = Value.Payload.BigInt{ |
| 7350 | try writer.writeAll(", "); | 7356 | .base = .{ .tag = if (c_limb_mut.positive) .int_big_positive else .int_big_negative }, |
| | 7357 | .data = c_limb_mut.limbs[0..c_limb_mut.len], |
| | 7358 | }; |
| 7351 | | 7359 | |
| 7352 | var lower_pl = Value.Payload.BigInt{ | 7360 | if (limb_offset > 0) try writer.writeAll(", "); |
| 7353 | .base = .{ .tag = .int_big_positive }, | 7361 | try formatIntLiteral(.{ |
| 7354 | .data = limbs[0..split], | 7362 | .dg = data.dg, |
| 7355 | }; | 7363 | .int_info = c_limb_int_info, |
| 7356 | const lower_val = Value.initPayload(&lower_pl.base); | 7364 | .kind = data.kind, |
| 7357 | try formatIntLiteral(.{ | 7365 | .cty = c_limb_cty, |
| 7358 | .ty = Type.u64, | 7366 | .val = Value.initPayload(&c_limb_val_pl.base), |
| 7359 | .val = lower_val, | 7367 | }, fmt, options, writer); |
| 7360 | .mod = data.mod, | 7368 | } |
| 7361 | }, fmt, options, writer); | | |
| 7362 | | | |
| 7363 | if (!int.positive and c_bits > 64 and !use_twos_comp) try writer.writeByte(')'); | | |
| 7364 | return writer.writeByte(')'); | | |
| 7365 | } | | |
| 7366 | | | |
| 7367 | switch (data.ty.tag()) { | | |
| 7368 | .c_short, .c_ushort, .c_int => {}, | | |
| 7369 | .c_uint => try writer.writeAll("u"), | | |
| 7370 | .c_long => try writer.writeAll("l"), | | |
| 7371 | .c_ulong => try writer.writeAll("ul"), | | |
| 7372 | .c_longlong => try writer.writeAll("ll"), | | |
| 7373 | .c_ulonglong => try writer.writeAll("ull"), | | |
| 7374 | else => try writer.writeByte(')'), | | |
| 7375 | } | 7369 | } |
| | 7370 | try data.cty.renderLiteralSuffix(writer); |
| 7376 | } | 7371 | } |
| 7377 | | 7372 | |
| 7378 | fn isByRef(ty: Type) bool { | 7373 | fn isByRef(ty: Type) bool { |