authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-03 00:18:34-05:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-05 02:59:01-05:00
log874ae81f1b2ae76cea6f5c79203f4baa68263163
tree685e469d6064e1c07f0ae8fa14f284fc6d9f5927
parente7f128c2051b086cdb1c03da041745b560bbaa3e

CBE: implement big integer literals


5 files changed, 504 insertions(+), 223 deletions(-)

lib/std/math/big/int.zig+1
...@@ -1674,6 +1674,7 @@ pub const Mutable = struct {...@@ -1674,6 +1674,7 @@ pub const Mutable = struct {
16741674
1675 /// If a is positive, this passes through to truncate.1675 /// If a is positive, this passes through to truncate.
1676 /// If a is negative, then r is set to positive with the bit pattern ~(a - 1).1676 /// If a is negative, then r is set to positive with the bit pattern ~(a - 1).
1677 /// r may alias a.
1677 ///1678 ///
1678 /// Asserts `r` has enough storage to store the result.1679 /// Asserts `r` has enough storage to store the result.
1679 /// The upper bound is `calcTwosCompLimbCount(a.len)`.1680 /// The upper bound is `calcTwosCompLimbCount(a.len)`.
lib/zig.h+6-6
...@@ -1360,8 +1360,8 @@ typedef signed __int128 zig_i128;...@@ -1360,8 +1360,8 @@ typedef signed __int128 zig_i128;
13601360
1361#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))1361#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1362#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))1362#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
1363#define zig_make_constant_u128(hi, lo) zig_make_u128(hi, lo)1363#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
1364#define zig_make_constant_i128(hi, lo) zig_make_i128(hi, lo)1364#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
1365#define zig_hi_u128(val) ((uint64_t)((val) >> 64))1365#define zig_hi_u128(val) ((uint64_t)((val) >> 64))
1366#define zig_lo_u128(val) ((uint64_t)((val) >> 0))1366#define zig_lo_u128(val) ((uint64_t)((val) >> 0))
1367#define zig_hi_i128(val) (( int64_t)((val) >> 64))1367#define zig_hi_i128(val) (( int64_t)((val) >> 64))
...@@ -1391,11 +1391,11 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;...@@ -1391,11 +1391,11 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
1391#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })1391#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
13921392
1393#if _MSC_VER /* MSVC doesn't allow struct literals in constant expressions */1393#if _MSC_VER /* MSVC doesn't allow struct literals in constant expressions */
1394#define zig_make_constant_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }1394#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1395#define zig_make_constant_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }1395#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1396#else /* But non-MSVC doesn't like the unprotected commas */1396#else /* But non-MSVC doesn't like the unprotected commas */
1397#define zig_make_constant_u128(hi, lo) zig_make_u128(hi, lo)1397#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
1398#define zig_make_constant_i128(hi, lo) zig_make_i128(hi, lo)1398#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
1399#endif1399#endif
1400#define zig_hi_u128(val) ((val).hi)1400#define zig_hi_u128(val) ((val).hi)
1401#define zig_lo_u128(val) ((val).lo)1401#define zig_lo_u128(val) ((val).lo)
src/codegen/c.zig+180-185
...@@ -449,7 +449,7 @@ pub const Function = struct {...@@ -449,7 +449,7 @@ pub const Function = struct {
449 }449 }
450450
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 }
454454
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);
575575
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 }
582582
...@@ -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 {
831835
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 }
18941898
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};
19381933
1939const CTypeFix = enum { prefix, suffix };1934const 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);
24512446
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);
25032498
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);
25062504
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);
25122510
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 });
25222522
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 {
25352535
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");
25402545
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}
71797184
7180const FormatIntLiteralContext = struct { ty: Type, val: Value, mod: *Module, location: ?ValueRenderLocation = null };7185const FormatIntLiteralContext = struct {
7186 dg: *DeclGen,
7187 int_info: std.builtin.Type.Int,
7188 kind: CType.Kind,
7189 cty: CType,
7190 val: Value,
7191};
7181fn formatIntLiteral(7192fn 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);
71897199
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 };
71987204
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();
72057213
7206 var undef_limbs: []BigIntLimb = &.{};7214 var undef_limbs: []BigIntLimb = &.{};
...@@ -7208,7 +7216,7 @@ fn formatIntLiteral(...@@ -7208,7 +7216,7 @@ fn formatIntLiteral(
72087216
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));
72137221
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));
72237231
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();
72277235
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) or7239 .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 }
72627250
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 initializers7260 .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);
72797282
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 };
73107307
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);
73187315 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 expressions7317
7321 // - negating the f80 int representation (i128) doesn't make sense7318 var c_limb_int_info = std.builtin.Type.Int{
7322 // Instead we write out the literal as a negative number in twos complement7319 .signedness = undefined,
7323 var limbs = int.limbs;7320 .bits = @intCast(u16, @divExact(c_bits, c_limb_info.count)),
73247321 };
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);
73317337
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 {
73357341 // 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 }
73497355 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 };
73517359
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}
73777372
7378fn isByRef(ty: Type) bool {7373fn isByRef(ty: Type) bool {
src/codegen/c/type.zig+317-31
...@@ -496,6 +496,296 @@ pub const CType = extern union {...@@ -496,6 +496,296 @@ pub const CType = extern union {
496 }496 }
497 };497 };
498498
499 pub fn toSigned(self: CType) CType {
500 return CType.initTag(switch (self.tag()) {
501 .char, .@"signed char", .@"unsigned char" => .@"signed char",
502 .short, .@"unsigned short" => .short,
503 .int, .@"unsigned int" => .int,
504 .long, .@"unsigned long" => .long,
505 .@"long long", .@"unsigned long long" => .@"long long",
506 .size_t, .ptrdiff_t => .ptrdiff_t,
507 .uint8_t, .int8_t => .int8_t,
508 .uint16_t, .int16_t => .int16_t,
509 .uint32_t, .int32_t => .int32_t,
510 .uint64_t, .int64_t => .int64_t,
511 .uintptr_t, .intptr_t => .intptr_t,
512 .zig_u128, .zig_i128 => .zig_i128,
513 .float,
514 .double,
515 .@"long double",
516 .zig_f16,
517 .zig_f32,
518 .zig_f80,
519 .zig_f128,
520 .zig_c_longdouble,
521 => |t| t,
522 else => unreachable,
523 });
524 }
525
526 pub fn toUnsigned(self: CType) CType {
527 return CType.initTag(switch (self.tag()) {
528 .char, .@"signed char", .@"unsigned char" => .@"unsigned char",
529 .short, .@"unsigned short" => .@"unsigned short",
530 .int, .@"unsigned int" => .@"unsigned int",
531 .long, .@"unsigned long" => .@"unsigned long",
532 .@"long long", .@"unsigned long long" => .@"unsigned long long",
533 .size_t, .ptrdiff_t => .size_t,
534 .uint8_t, .int8_t => .uint8_t,
535 .uint16_t, .int16_t => .uint16_t,
536 .uint32_t, .int32_t => .uint32_t,
537 .uint64_t, .int64_t => .uint64_t,
538 .uintptr_t, .intptr_t => .uintptr_t,
539 .zig_u128, .zig_i128 => .zig_u128,
540 else => unreachable,
541 });
542 }
543
544 pub fn getStandardDefineAbbrev(self: CType) ?[]const u8 {
545 return switch (self.tag()) {
546 .char => "CHAR",
547 .@"signed char" => "SCHAR",
548 .short => "SHRT",
549 .int => "INT",
550 .long => "LONG",
551 .@"long long" => "LLONG",
552 .@"unsigned char" => "UCHAR",
553 .@"unsigned short" => "USHRT",
554 .@"unsigned int" => "UINT",
555 .@"unsigned long" => "ULONG",
556 .@"unsigned long long" => "ULLONG",
557 .float => "FLT",
558 .double => "DBL",
559 .@"long double" => "LDBL",
560 .size_t => "SIZE",
561 .ptrdiff_t => "PTRDIFF",
562 .uint8_t => "UINT8",
563 .int8_t => "INT8",
564 .uint16_t => "UINT16",
565 .int16_t => "INT16",
566 .uint32_t => "UINT32",
567 .int32_t => "INT32",
568 .uint64_t => "UINT64",
569 .int64_t => "INT64",
570 .uintptr_t => "UINTPTR",
571 .intptr_t => "INTPTR",
572 else => null,
573 };
574 }
575
576 pub fn renderLiteralPrefix(self: CType, writer: anytype, kind: Kind) @TypeOf(writer).Error!void {
577 switch (self.tag()) {
578 .void => unreachable,
579 ._Bool,
580 .char,
581 .@"signed char",
582 .short,
583 .@"unsigned short",
584 .bool,
585 .size_t,
586 .ptrdiff_t,
587 .uintptr_t,
588 .intptr_t,
589 => |t| switch (kind) {
590 else => try writer.print("({s})", .{@tagName(t)}),
591 .global => {},
592 },
593 .int,
594 .long,
595 .@"long long",
596 .@"unsigned char",
597 .@"unsigned int",
598 .@"unsigned long",
599 .@"unsigned long long",
600 .float,
601 .double,
602 .@"long double",
603 => {},
604 .uint8_t,
605 .int8_t,
606 .uint16_t,
607 .int16_t,
608 .uint32_t,
609 .int32_t,
610 .uint64_t,
611 .int64_t,
612 => try writer.print("{s}_C(", .{self.getStandardDefineAbbrev().?}),
613 .zig_u128,
614 .zig_i128,
615 .zig_f16,
616 .zig_f32,
617 .zig_f64,
618 .zig_f80,
619 .zig_f128,
620 .zig_c_longdouble,
621 => |t| try writer.print("zig_{s}_{s}(", .{
622 switch (kind) {
623 else => "make",
624 .global => "init",
625 },
626 @tagName(t)["zig_".len..],
627 }),
628 .pointer,
629 .pointer_const,
630 .pointer_volatile,
631 .pointer_const_volatile,
632 => unreachable,
633 .array,
634 .vector,
635 => try writer.writeByte('{'),
636 .fwd_anon_struct,
637 .fwd_anon_union,
638 .fwd_struct,
639 .fwd_union,
640 .unnamed_struct,
641 .unnamed_union,
642 .packed_unnamed_struct,
643 .packed_unnamed_union,
644 .anon_struct,
645 .anon_union,
646 .@"struct",
647 .@"union",
648 .packed_struct,
649 .packed_union,
650 .function,
651 .varargs_function,
652 => unreachable,
653 }
654 }
655
656 pub fn renderLiteralSuffix(self: CType, writer: anytype) @TypeOf(writer).Error!void {
657 switch (self.tag()) {
658 .void => unreachable,
659 ._Bool => {},
660 .char,
661 .@"signed char",
662 .short,
663 .int,
664 => {},
665 .long => try writer.writeByte('l'),
666 .@"long long" => try writer.writeAll("ll"),
667 .@"unsigned char",
668 .@"unsigned short",
669 .@"unsigned int",
670 => try writer.writeByte('u'),
671 .@"unsigned long",
672 .size_t,
673 .uintptr_t,
674 => try writer.writeAll("ul"),
675 .@"unsigned long long" => try writer.writeAll("ull"),
676 .float => try writer.writeByte('f'),
677 .double => {},
678 .@"long double" => try writer.writeByte('l'),
679 .bool,
680 .ptrdiff_t,
681 .intptr_t,
682 => {},
683 .uint8_t,
684 .int8_t,
685 .uint16_t,
686 .int16_t,
687 .uint32_t,
688 .int32_t,
689 .uint64_t,
690 .int64_t,
691 .zig_u128,
692 .zig_i128,
693 .zig_f16,
694 .zig_f32,
695 .zig_f64,
696 .zig_f80,
697 .zig_f128,
698 .zig_c_longdouble,
699 => try writer.writeByte(')'),
700 .pointer,
701 .pointer_const,
702 .pointer_volatile,
703 .pointer_const_volatile,
704 => unreachable,
705 .array,
706 .vector,
707 => try writer.writeByte('}'),
708 .fwd_anon_struct,
709 .fwd_anon_union,
710 .fwd_struct,
711 .fwd_union,
712 .unnamed_struct,
713 .unnamed_union,
714 .packed_unnamed_struct,
715 .packed_unnamed_union,
716 .anon_struct,
717 .anon_union,
718 .@"struct",
719 .@"union",
720 .packed_struct,
721 .packed_union,
722 .function,
723 .varargs_function,
724 => unreachable,
725 }
726 }
727
728 pub fn byteSize(self: CType, store: Store.Set, target: Target) u64 {
729 return switch (self.tag()) {
730 .void => 0,
731 .char, .@"signed char", ._Bool, .@"unsigned char", .bool, .uint8_t, .int8_t => 1,
732 .short => target.c_type_byte_size(.short),
733 .int => target.c_type_byte_size(.int),
734 .long => target.c_type_byte_size(.long),
735 .@"long long" => target.c_type_byte_size(.longlong),
736 .@"unsigned short" => target.c_type_byte_size(.ushort),
737 .@"unsigned int" => target.c_type_byte_size(.uint),
738 .@"unsigned long" => target.c_type_byte_size(.ulong),
739 .@"unsigned long long" => target.c_type_byte_size(.ulonglong),
740 .float => target.c_type_byte_size(.float),
741 .double => target.c_type_byte_size(.double),
742 .@"long double" => target.c_type_byte_size(.longdouble),
743 .size_t,
744 .ptrdiff_t,
745 .uintptr_t,
746 .intptr_t,
747 .pointer,
748 .pointer_const,
749 .pointer_volatile,
750 .pointer_const_volatile,
751 => @divExact(target.cpu.arch.ptrBitWidth(), 8),
752 .uint16_t, .int16_t, .zig_f16 => 2,
753 .uint32_t, .int32_t, .zig_f32 => 4,
754 .uint64_t, .int64_t, .zig_f64 => 8,
755 .zig_u128, .zig_i128, .zig_f128 => 16,
756 .zig_f80 => if (target.c_type_bit_size(.longdouble) == 80)
757 target.c_type_byte_size(.longdouble)
758 else
759 16,
760 .zig_c_longdouble => target.c_type_byte_size(.longdouble),
761
762 .array,
763 .vector,
764 => {
765 const data = self.cast(Payload.Sequence).?.data;
766 return data.len * store.indexToCType(data.elem_type).byteSize(store, target);
767 },
768
769 .fwd_anon_struct,
770 .fwd_anon_union,
771 .fwd_struct,
772 .fwd_union,
773 .unnamed_struct,
774 .unnamed_union,
775 .packed_unnamed_struct,
776 .packed_unnamed_union,
777 .anon_struct,
778 .anon_union,
779 .@"struct",
780 .@"union",
781 .packed_struct,
782 .packed_union,
783 .function,
784 .varargs_function,
785 => unreachable,
786 };
787 }
788
499 pub fn isPacked(self: CType) bool {789 pub fn isPacked(self: CType) bool {
500 return switch (self.tag()) {790 return switch (self.tag()) {
501 else => false,791 else => false,
...@@ -787,26 +1077,26 @@ pub const CType = extern union {...@@ -787,26 +1077,26 @@ pub const CType = extern union {
787 };1077 };
788 }1078 }
7891079
790 fn tagFromIntInfo(signedness: std.builtin.Signedness, bits: u16) Tag {1080 fn tagFromIntInfo(int_info: std.builtin.Type.Int) Tag {
791 return switch (bits) {1081 return switch (int_info.bits) {
792 0 => .void,1082 0 => .void,
793 1...8 => switch (signedness) {1083 1...8 => switch (int_info.signedness) {
794 .unsigned => .uint8_t,1084 .unsigned => .uint8_t,
795 .signed => .int8_t,1085 .signed => .int8_t,
796 },1086 },
797 9...16 => switch (signedness) {1087 9...16 => switch (int_info.signedness) {
798 .unsigned => .uint16_t,1088 .unsigned => .uint16_t,
799 .signed => .int16_t,1089 .signed => .int16_t,
800 },1090 },
801 17...32 => switch (signedness) {1091 17...32 => switch (int_info.signedness) {
802 .unsigned => .uint32_t,1092 .unsigned => .uint32_t,
803 .signed => .int32_t,1093 .signed => .int32_t,
804 },1094 },
805 33...64 => switch (signedness) {1095 33...64 => switch (int_info.signedness) {
806 .unsigned => .uint64_t,1096 .unsigned => .uint64_t,
807 .signed => .int64_t,1097 .signed => .int64_t,
808 },1098 },
809 65...128 => switch (signedness) {1099 65...128 => switch (int_info.signedness) {
810 .unsigned => .zig_u128,1100 .unsigned => .zig_u128,
811 .signed => .zig_i128,1101 .signed => .zig_i128,
812 },1102 },
...@@ -945,31 +1235,27 @@ pub const CType = extern union {...@@ -945,31 +1235,27 @@ pub const CType = extern union {
945 .c_ulong => self.init(.@"unsigned long"),1235 .c_ulong => self.init(.@"unsigned long"),
946 .c_longlong => self.init(.@"long long"),1236 .c_longlong => self.init(.@"long long"),
947 .c_ulonglong => self.init(.@"unsigned long long"),1237 .c_ulonglong => self.init(.@"unsigned long long"),
948 else => {1238 else => switch (tagFromIntInfo(ty.intInfo(target))) {
949 const info = ty.intInfo(target);1239 .void => unreachable,
950 const t = tagFromIntInfo(info.signedness, info.bits);1240 else => |t| self.init(t),
951 switch (t) {1241 .array => switch (kind) {
952 .void => unreachable,1242 .forward, .complete, .global => {
953 else => self.init(t),1243 const abi_size = ty.abiSize(target);
954 .array => switch (kind) {1244 const abi_align = ty.abiAlignment(target);
955 .forward, .complete, .global => {1245 self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{
956 const abi_size = ty.abiSize(target);1246 .len = @divExact(abi_size, abi_align),
957 const abi_align = ty.abiAlignment(target);1247 .elem_type = tagFromIntInfo(.{
958 self.storage = .{ .seq = .{ .base = .{ .tag = .array }, .data = .{1248 .signedness = .unsigned,
959 .len = @divExact(abi_size, abi_align),1249 .bits = @intCast(u16, abi_align * 8),
960 .elem_type = tagFromIntInfo(1250 }).toIndex(),
961 .unsigned,1251 } } };
962 @intCast(u16, abi_align * 8),1252 self.value = .{ .cty = initPayload(&self.storage.seq) };
963 ).toIndex(),
964 } } };
965 self.value = .{ .cty = initPayload(&self.storage.seq) };
966 },
967 .forward_parameter,
968 .parameter,
969 => try self.initArrayParameter(ty, kind, lookup),
970 .payload => unreachable,
971 },1253 },
972 }1254 .forward_parameter,
1255 .parameter,
1256 => try self.initArrayParameter(ty, kind, lookup),
1257 .payload => unreachable,
1258 },
973 },1259 },
974 } else switch (ty.zigTypeTag()) {1260 } else switch (ty.zigTypeTag()) {
975 .Frame => unreachable,1261 .Frame => unreachable,
test/behavior/bitcast.zig-1
...@@ -368,7 +368,6 @@ test "comptime @bitCast packed struct to int and back" {...@@ -368,7 +368,6 @@ test "comptime @bitCast packed struct to int and back" {
368}368}
369369
370test "comptime bitcast with fields following f80" {370test "comptime bitcast with fields following f80" {
371 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
372 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;371 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
373 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;372 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
374 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;373 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;