| ... | ... | @@ -449,7 +449,7 @@ pub const Function = struct { |
| 449 | 449 | } |
| 450 | 450 | |
| 451 | 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 | 455 | fn getLazyFnName(f: *Function, key: LazyFnKey, data: LazyFnValue.Data) ![]const u8 { |
| ... | ... | @@ -574,9 +574,9 @@ pub const DeclGen = struct { |
| 574 | 574 | const len_val = Value.initPayload(&len_pl.base); |
| 575 | 575 | |
| 576 | 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 | 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 | 606 | try writer.writeByte(')'); |
| 607 | 607 | } |
| 608 | 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 | 610 | .decl_ref_mut, .decl_ref, .variable => { |
| 611 | 611 | const decl_index = switch (ptr_val.tag()) { |
| 612 | 612 | .decl_ref => ptr_val.castTag(.decl_ref).?.data, |
| ... | ... | @@ -670,7 +670,9 @@ pub const DeclGen = struct { |
| 670 | 670 | container_ptr_ty, |
| 671 | 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 | 677 | .end => { |
| 676 | 678 | try writer.writeAll("(("); |
| ... | ... | @@ -680,7 +682,9 @@ pub const DeclGen = struct { |
| 680 | 682 | container_ptr_ty, |
| 681 | 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 | 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 | 754 | .Float => { |
| 751 | 755 | const bits = ty.floatBits(target); |
| 752 | 756 | var int_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits }; |
| ... | ... | @@ -780,11 +784,11 @@ pub const DeclGen = struct { |
| 780 | 784 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 781 | 785 | const ptr_ty = ty.slicePtrFieldType(&buf); |
| 782 | 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 | 788 | } else { |
| 785 | 789 | try writer.writeAll("(("); |
| 786 | 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 | 793 | .Optional => { |
| 790 | 794 | var opt_buf: Type.Payload.ElemType = undefined; |
| ... | ... | @@ -831,7 +835,7 @@ pub const DeclGen = struct { |
| 831 | 835 | |
| 832 | 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 | 840 | .Union => { |
| 837 | 841 | if (!location.isInitializer()) { |
| ... | ... | @@ -854,7 +858,7 @@ pub const DeclGen = struct { |
| 854 | 858 | if (!field.ty.hasRuntimeBits()) continue; |
| 855 | 859 | try dg.renderValue(writer, field.ty, val, initializer_type); |
| 856 | 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 | 862 | if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}'); |
| 859 | 863 | return writer.writeByte('}'); |
| 860 | 864 | }, |
| ... | ... | @@ -868,7 +872,7 @@ pub const DeclGen = struct { |
| 868 | 872 | try writer.writeAll("{ .payload = "); |
| 869 | 873 | try dg.renderValue(writer, ty.errorUnionPayload(), val, initializer_type); |
| 870 | 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 | 878 | .Array, .Vector => { |
| ... | ... | @@ -927,7 +931,7 @@ pub const DeclGen = struct { |
| 927 | 931 | .decl_ref_mut, |
| 928 | 932 | .decl_ref, |
| 929 | 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 | 936 | .Float => { |
| 933 | 937 | const bits = ty.floatBits(target); |
| ... | ... | @@ -1020,7 +1024,7 @@ pub const DeclGen = struct { |
| 1020 | 1024 | try writer.writeAll(", "); |
| 1021 | 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 | 1028 | if (!empty) try writer.writeByte(')'); |
| 1025 | 1029 | return; |
| 1026 | 1030 | }, |
| ... | ... | @@ -1069,7 +1073,7 @@ pub const DeclGen = struct { |
| 1069 | 1073 | .int_u64, .one => { |
| 1070 | 1074 | try writer.writeAll("(("); |
| 1071 | 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 | 1078 | .field_ptr, |
| 1075 | 1079 | .elem_ptr, |
| ... | ... | @@ -1889,11 +1893,11 @@ pub const DeclGen = struct { |
| 1889 | 1893 | const int_info = ty.intInfo(target); |
| 1890 | 1894 | if (int_info.signedness == .signed) { |
| 1891 | 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 | 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 | 1902 | .Bits => { |
| 1899 | 1903 | var bits_pl = Value.Payload.U64{ |
| ... | ... | @@ -1901,7 +1905,7 @@ pub const DeclGen = struct { |
| 1901 | 1905 | .data = ty.bitSize(target), |
| 1902 | 1906 | }; |
| 1903 | 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 | 1914 | dg: *DeclGen, |
| 1911 | 1915 | ty: Type, |
| 1912 | 1916 | val: Value, |
| 1917 | loc: ValueRenderLocation, |
| 1913 | 1918 | ) !std.fmt.Formatter(formatIntLiteral) { |
| 1914 | | const int_info = ty.intInfo(dg.module.getTarget()); |
| 1915 | | const c_bits = toCIntBits(int_info.bits); |
| 1916 | | if (c_bits == null or c_bits.? > 128) |
| 1917 | | return dg.fail("TODO implement integer constants larger than 128 bits", .{}); |
| 1919 | const kind: CType.Kind = switch (loc) { |
| 1920 | .FunctionArgument => .parameter, |
| 1921 | .Initializer, .Other => .complete, |
| 1922 | .StaticInitializer => .global, |
| 1923 | }; |
| 1918 | 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 | 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 | 1934 | const CTypeFix = enum { prefix, suffix }; |
| ... | ... | @@ -2450,7 +2445,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 2450 | 2445 | const len_val = Value.initPayload(&len_pl.base); |
| 2451 | 2446 | |
| 2452 | 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 | 2451 | try writer.writeAll("};\n"); |
| ... | ... | @@ -2501,7 +2496,10 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2501 | 2496 | var int_pl: Value.Payload.U64 = undefined; |
| 2502 | 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 | 2503 | const name_ty = Type.initPayload(&name_ty_pl.base); |
| 2506 | 2504 | |
| 2507 | 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 | 2508 | var len_pl = Value.Payload.U64{ .base = .{ .tag = .int_u64 }, .data = name.len }; |
| 2511 | 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 | 2514 | try o.dg.renderTypeAndName(w, name_ty, .{ .identifier = "name" }, Const, 0, .complete); |
| 2515 | 2515 | try w.writeAll(" = "); |
| 2516 | 2516 | try o.dg.renderValue(w, name_ty, name_val, .Initializer); |
| 2517 | 2517 | try w.writeAll(";\n return ("); |
| 2518 | 2518 | try o.dg.renderType(w, name_slice_ty); |
| 2519 | 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 | 2523 | try w.writeAll(" }\n"); |
| ... | ... | @@ -2535,7 +2535,12 @@ pub fn genLazyFn(o: *Object, lazy_fn: LazyFnMap.Entry) !void { |
| 2535 | 2535 | |
| 2536 | 2536 | const fwd_decl_writer = o.dg.fwd_decl.writer(); |
| 2537 | 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 | 2544 | try fwd_decl_writer.writeAll(";\n"); |
| 2540 | 2545 | |
| 2541 | 2546 | try w.print("static zig_{s} ", .{@tagName(key)}); |
| ... | ... | @@ -7177,30 +7182,33 @@ fn undefPattern(comptime IntType: type) IntType { |
| 7177 | 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 | 7192 | fn formatIntLiteral( |
| 7182 | 7193 | data: FormatIntLiteralContext, |
| 7183 | 7194 | comptime fmt: []const u8, |
| 7184 | 7195 | options: std.fmt.FormatOptions, |
| 7185 | 7196 | writer: anytype, |
| 7186 | 7197 | ) @TypeOf(writer).Error!void { |
| 7187 | | const target = data.mod.getTarget(); |
| 7188 | | const int_info = data.ty.intInfo(target); |
| 7198 | const target = data.dg.module.getTarget(); |
| 7189 | 7199 | |
| 7190 | 7200 | const ExpectedContents = struct { |
| 7191 | 7201 | const base = 10; |
| 7192 | | const limbs_count_128 = BigInt.calcTwosCompLimbCount(128); |
| 7193 | | const expected_needed_limbs_count = BigInt.calcToStringLimbsBufferLen(limbs_count_128, base); |
| 7194 | | const worst_case_int = BigInt.Const{ |
| 7195 | | .limbs = &([1]BigIntLimb{std.math.maxInt(BigIntLimb)} ** expected_needed_limbs_count), |
| 7196 | | .positive = false, |
| 7197 | | }; |
| 7202 | const bits = 128; |
| 7203 | const limbs_count = BigInt.calcTwosCompLimbCount(bits); |
| 7198 | 7204 | |
| 7199 | | undef_limbs: [limbs_count_128]BigIntLimb, |
| 7200 | | wrap_limbs: [limbs_count_128]BigIntLimb, |
| 7205 | undef_limbs: [limbs_count]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 | 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 | 7212 | const allocator = stack.get(); |
| 7205 | 7213 | |
| 7206 | 7214 | var undef_limbs: []BigIntLimb = &.{}; |
| ... | ... | @@ -7208,7 +7216,7 @@ fn formatIntLiteral( |
| 7208 | 7216 | |
| 7209 | 7217 | var int_buf: Value.BigIntSpace = undefined; |
| 7210 | 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 | 7220 | std.mem.set(BigIntLimb, undef_limbs, undefPattern(BigIntLimb)); |
| 7213 | 7221 | |
| 7214 | 7222 | var undef_int = BigInt.Mutable{ |
| ... | ... | @@ -7216,163 +7224,150 @@ fn formatIntLiteral( |
| 7216 | 7224 | .len = undef_limbs.len, |
| 7217 | 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 | 7228 | break :blk undef_int.toConst(); |
| 7221 | 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 | 7233 | var one_limbs: [BigInt.calcLimbLen(1)]BigIntLimb = undefined; |
| 7226 | 7234 | const one = BigInt.Mutable.init(&one_limbs, 1).toConst(); |
| 7227 | 7235 | |
| 7228 | | const wrap_limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)); |
| 7229 | | defer allocator.free(wrap_limbs); |
| 7230 | | var wrap = BigInt.Mutable{ .limbs = wrap_limbs, .len = undefined, .positive = undefined }; |
| 7231 | | if (wrap.addWrap(int, one, int_info.signedness, c_bits) or |
| 7232 | | int_info.signedness == .signed and wrap.subWrap(int, one, int_info.signedness, c_bits)) |
| 7233 | | { |
| 7234 | | const abbrev = switch (data.ty.tag()) { |
| 7235 | | .c_short, .c_ushort => "SHRT", |
| 7236 | | .c_int, .c_uint => "INT", |
| 7237 | | .c_long, .c_ulong => "LONG", |
| 7238 | | .c_longlong, .c_ulonglong => "LLONG", |
| 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, |
| 7236 | var wrap = BigInt.Mutable{ |
| 7237 | .limbs = try allocator.alloc(BigIntLimb, BigInt.calcTwosCompLimbCount(c_bits)), |
| 7238 | .len = undefined, |
| 7239 | .positive = undefined, |
| 7240 | }; |
| 7241 | defer allocator.free(wrap.limbs); |
| 7242 | if (wrap.addWrap(int, one, data.int_info.signedness, c_bits) or |
| 7243 | data.int_info.signedness == .signed and wrap.subWrap(int, one, data.int_info.signedness, c_bits)) |
| 7244 | return writer.print("{s}_{s}", .{ |
| 7245 | data.cty.getStandardDefineAbbrev() orelse return writer.print("zig_{s}Int_{c}{d}", .{ |
| 7246 | if (int.positive) "max" else "min", signAbbrev(data.int_info.signedness), c_bits, |
| 7242 | 7247 | }), |
| 7243 | | }; |
| 7244 | | if (int_info.signedness == .unsigned) try writer.writeByte('U'); |
| 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 | | } |
| 7248 | if (int.positive) "MAX" else "MIN", |
| 7249 | }); |
| 7262 | 7250 | |
| 7263 | | switch (data.ty.tag()) { |
| 7264 | | .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {}, |
| 7265 | | else => { |
| 7266 | | if (int_info.bits <= 64) { |
| 7267 | | try writer.print("{s}INT{d}_C(", .{ switch (int_info.signedness) { |
| 7268 | | .signed => "", |
| 7269 | | .unsigned => "U", |
| 7270 | | }, c_bits }); |
| 7271 | | } else if (data.location != null and data.location.? == .StaticInitializer) { |
| 7272 | | // MSVC treats casting the struct initializer as not constant (C2099), so an alternate form is used in global initializers |
| 7273 | | try writer.print("zig_make_constant_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }); |
| 7274 | | } else { |
| 7275 | | try writer.print("zig_make_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }); |
| 7276 | | } |
| 7251 | const c_limb_info: struct { |
| 7252 | cty: CType, |
| 7253 | count: usize, |
| 7254 | endian: std.builtin.Endian, |
| 7255 | homogeneous: bool, |
| 7256 | } = switch (data.cty.tag()) { |
| 7257 | else => .{ |
| 7258 | .cty = CType.initTag(.void), |
| 7259 | .count = 1, |
| 7260 | .endian = .Little, |
| 7261 | .homogeneous = true, |
| 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)); |
| 7281 | | if (c_bits <= 64) { |
| 7282 | | var base: u8 = undefined; |
| 7283 | | var case: std.fmt.Case = undefined; |
| 7284 | | switch (fmt.len) { |
| 7285 | | 0 => base = 10, |
| 7283 | const style: struct { base: u8, case: std.fmt.Case = undefined } = switch (fmt.len) { |
| 7284 | 0 => .{ .base = 10 }, |
| 7286 | 7285 | 1 => switch (fmt[0]) { |
| 7287 | | 'b' => { |
| 7288 | | base = 2; |
| 7286 | 'b' => style: { |
| 7289 | 7287 | try writer.writeAll("0b"); |
| 7288 | break :style .{ .base = 2 }; |
| 7290 | 7289 | }, |
| 7291 | | 'o' => { |
| 7292 | | base = 8; |
| 7290 | 'o' => style: { |
| 7293 | 7291 | try writer.writeByte('0'); |
| 7292 | break :style .{ .base = 8 }; |
| 7294 | 7293 | }, |
| 7295 | | 'd' => base = 10, |
| 7296 | | 'x' => { |
| 7297 | | base = 16; |
| 7298 | | case = .lower; |
| 7299 | | try writer.writeAll("0x"); |
| 7300 | | }, |
| 7301 | | 'X' => { |
| 7302 | | base = 16; |
| 7303 | | case = .upper; |
| 7294 | 'd' => .{ .base = 10 }, |
| 7295 | 'x', 'X' => |base| style: { |
| 7304 | 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 | 7303 | else => @compileError("Invalid fmt: " ++ fmt), |
| 7307 | 7304 | }, |
| 7308 | 7305 | else => @compileError("Invalid fmt: " ++ fmt), |
| 7309 | | } |
| 7306 | }; |
| 7310 | 7307 | |
| 7311 | | var str: [64]u8 = undefined; |
| 7312 | | var limbs_buf: [BigInt.calcToStringLimbsBufferLen(limbs_count_64, 10)]BigIntLimb = undefined; |
| 7313 | | try writer.writeAll(str[0..int.abs().toString(&str, base, case, &limbs_buf)]); |
| 7308 | const string = try int.abs().toStringAlloc(allocator, style.base, style.case); |
| 7309 | defer allocator.free(string); |
| 7310 | try writer.writeAll(string); |
| 7314 | 7311 | } else { |
| 7315 | | assert(c_bits == 128); |
| 7316 | | const split = std.math.min(int.limbs.len, limbs_count_64); |
| 7317 | | var twos_comp_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; |
| 7318 | | |
| 7319 | | // Adding a negation in the C code before the doesn't work in all cases: |
| 7320 | | // - struct versions would require an extra zig_sub_ call to negate, which wouldn't work in constant expressions |
| 7321 | | // - negating the f80 int representation (i128) doesn't make sense |
| 7322 | | // Instead we write out the literal as a negative number in twos complement |
| 7323 | | var limbs = int.limbs; |
| 7324 | | |
| 7325 | | if (use_twos_comp) { |
| 7326 | | var twos_comp = BigInt.Mutable{ |
| 7327 | | .limbs = &twos_comp_limbs, |
| 7328 | | .positive = undefined, |
| 7312 | try data.cty.renderLiteralPrefix(writer, data.kind); |
| 7313 | wrap.convertToTwosComplement(int, .unsigned, data.int_info.bits); |
| 7314 | std.mem.set(BigIntLimb, wrap.limbs[wrap.len..], 0); |
| 7315 | wrap.len = wrap.limbs.len; |
| 7316 | const limbs_per_c_limb = @divExact(wrap.len, c_limb_info.count); |
| 7317 | |
| 7318 | var c_limb_int_info = std.builtin.Type.Int{ |
| 7319 | .signedness = undefined, |
| 7320 | .bits = @intCast(u16, @divExact(c_bits, c_limb_info.count)), |
| 7321 | }; |
| 7322 | var c_limb_cty: CType = undefined; |
| 7323 | |
| 7324 | var limb_offset: usize = 0; |
| 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 | 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); |
| 7333 | | limbs = twos_comp.limbs; |
| 7334 | | } |
| 7335 | | |
| 7336 | | var upper_pl = Value.Payload.BigInt{ |
| 7337 | | .base = .{ .tag = .int_big_positive }, |
| 7338 | | .data = limbs[split..], |
| 7339 | | }; |
| 7340 | | const upper_val = Value.initPayload(&upper_pl.base); |
| 7341 | | try formatIntLiteral(.{ |
| 7342 | | .ty = switch (int_info.signedness) { |
| 7343 | | .unsigned => Type.u64, |
| 7344 | | .signed => if (use_twos_comp) Type.u64 else Type.i64, |
| 7345 | | }, |
| 7346 | | .val = upper_val, |
| 7347 | | .mod = data.mod, |
| 7348 | | }, fmt, options, writer); |
| 7349 | | |
| 7350 | | try writer.writeAll(", "); |
| 7338 | if (limb_i == most_significant_limb_i and |
| 7339 | !c_limb_info.homogeneous and data.int_info.signedness == .signed) |
| 7340 | { |
| 7341 | // most significant limb is actually signed |
| 7342 | c_limb_int_info.signedness = .signed; |
| 7343 | c_limb_cty = c_limb_info.cty.toSigned(); |
| 7344 | |
| 7345 | c_limb_mut.positive = wrap.positive; |
| 7346 | c_limb_mut.convertToTwosComplement( |
| 7347 | c_limb_mut.toConst(), |
| 7348 | .signed, |
| 7349 | data.int_info.bits - limb_i * @bitSizeOf(BigIntLimb), |
| 7350 | ); |
| 7351 | } else { |
| 7352 | c_limb_int_info.signedness = .unsigned; |
| 7353 | c_limb_cty = c_limb_info.cty; |
| 7354 | } |
| 7355 | var c_limb_val_pl = Value.Payload.BigInt{ |
| 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{ |
| 7353 | | .base = .{ .tag = .int_big_positive }, |
| 7354 | | .data = limbs[0..split], |
| 7355 | | }; |
| 7356 | | const lower_val = Value.initPayload(&lower_pl.base); |
| 7357 | | try formatIntLiteral(.{ |
| 7358 | | .ty = Type.u64, |
| 7359 | | .val = lower_val, |
| 7360 | | .mod = data.mod, |
| 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(')'), |
| 7360 | if (limb_offset > 0) try writer.writeAll(", "); |
| 7361 | try formatIntLiteral(.{ |
| 7362 | .dg = data.dg, |
| 7363 | .int_info = c_limb_int_info, |
| 7364 | .kind = data.kind, |
| 7365 | .cty = c_limb_cty, |
| 7366 | .val = Value.initPayload(&c_limb_val_pl.base), |
| 7367 | }, fmt, options, writer); |
| 7368 | } |
| 7375 | 7369 | } |
| 7370 | try data.cty.renderLiteralSuffix(writer); |
| 7376 | 7371 | } |
| 7377 | 7372 | |
| 7378 | 7373 | fn isByRef(ty: Type) bool { |