| ... | @@ -90,7 +90,15 @@ const FormatTypeAsCIdentContext = struct { | ... | @@ -90,7 +90,15 @@ const FormatTypeAsCIdentContext = struct { |
| 90 | const ValueRenderLocation = enum { | 90 | const ValueRenderLocation = enum { |
| 91 | FunctionArgument, | 91 | FunctionArgument, |
| 92 | Initializer, | 92 | Initializer, |
| | 93 | StaticInitializer, |
| 93 | Other, | 94 | Other, |
| | 95 | |
| | 96 | pub fn isInitializer(self: ValueRenderLocation) bool { |
| | 97 | return switch (self) { |
| | 98 | .Initializer, .StaticInitializer => true, |
| | 99 | else => false, |
| | 100 | }; |
| | 101 | } |
| 94 | }; | 102 | }; |
| 95 | | 103 | |
| 96 | const BuiltinInfo = enum { | 104 | const BuiltinInfo = enum { |
| ... | @@ -718,7 +726,7 @@ pub const DeclGen = struct { | ... | @@ -718,7 +726,7 @@ pub const DeclGen = struct { |
| 718 | return writer.writeAll("false"); | 726 | return writer.writeAll("false"); |
| 719 | } | 727 | } |
| 720 | }, | 728 | }, |
| 721 | .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, val)}), | 729 | .Int, .Enum, .ErrorSet => return writer.print("{x}", .{try dg.fmtIntLiteralLoc(ty, val, location)}), |
| 722 | .Float => { | 730 | .Float => { |
| 723 | const bits = ty.floatBits(target); | 731 | const bits = ty.floatBits(target); |
| 724 | var int_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits }; | 732 | var int_pl = Type.Payload.Bits{ .base = .{ .tag = .int_signed }, .data = bits }; |
| ... | @@ -742,7 +750,7 @@ pub const DeclGen = struct { | ... | @@ -742,7 +750,7 @@ pub const DeclGen = struct { |
| 742 | return writer.writeByte(')'); | 750 | return writer.writeByte(')'); |
| 743 | }, | 751 | }, |
| 744 | .Pointer => if (ty.isSlice()) { | 752 | .Pointer => if (ty.isSlice()) { |
| 745 | if (location != .Initializer) { | 753 | if (!location.isInitializer()) { |
| 746 | try writer.writeByte('('); | 754 | try writer.writeByte('('); |
| 747 | try dg.renderTypecast(writer, ty); | 755 | try dg.renderTypecast(writer, ty); |
| 748 | try writer.writeByte(')'); | 756 | try writer.writeByte(')'); |
| ... | @@ -770,7 +778,7 @@ pub const DeclGen = struct { | ... | @@ -770,7 +778,7 @@ pub const DeclGen = struct { |
| 770 | return dg.renderValue(writer, payload_ty, val, location); | 778 | return dg.renderValue(writer, payload_ty, val, location); |
| 771 | } | 779 | } |
| 772 | | 780 | |
| 773 | if (location != .Initializer) { | 781 | if (!location.isInitializer()) { |
| 774 | try writer.writeByte('('); | 782 | try writer.writeByte('('); |
| 775 | try dg.renderTypecast(writer, ty); | 783 | try dg.renderTypecast(writer, ty); |
| 776 | try writer.writeByte(')'); | 784 | try writer.writeByte(')'); |
| ... | @@ -784,7 +792,7 @@ pub const DeclGen = struct { | ... | @@ -784,7 +792,7 @@ pub const DeclGen = struct { |
| 784 | }, | 792 | }, |
| 785 | .Struct => switch (ty.containerLayout()) { | 793 | .Struct => switch (ty.containerLayout()) { |
| 786 | .Auto, .Extern => { | 794 | .Auto, .Extern => { |
| 787 | if (location != .Initializer) { | 795 | if (!location.isInitializer()) { |
| 788 | try writer.writeByte('('); | 796 | try writer.writeByte('('); |
| 789 | try dg.renderTypecast(writer, ty); | 797 | try dg.renderTypecast(writer, ty); |
| 790 | try writer.writeByte(')'); | 798 | try writer.writeByte(')'); |
| ... | @@ -806,7 +814,7 @@ pub const DeclGen = struct { | ... | @@ -806,7 +814,7 @@ pub const DeclGen = struct { |
| 806 | .Packed => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef)}), | 814 | .Packed => return writer.print("{x}", .{try dg.fmtIntLiteral(ty, Value.undef)}), |
| 807 | }, | 815 | }, |
| 808 | .Union => { | 816 | .Union => { |
| 809 | if (location != .Initializer) { | 817 | if (!location.isInitializer()) { |
| 810 | try writer.writeByte('('); | 818 | try writer.writeByte('('); |
| 811 | try dg.renderTypecast(writer, ty); | 819 | try dg.renderTypecast(writer, ty); |
| 812 | try writer.writeByte(')'); | 820 | try writer.writeByte(')'); |
| ... | @@ -831,7 +839,7 @@ pub const DeclGen = struct { | ... | @@ -831,7 +839,7 @@ pub const DeclGen = struct { |
| 831 | return writer.writeByte('}'); | 839 | return writer.writeByte('}'); |
| 832 | }, | 840 | }, |
| 833 | .ErrorUnion => { | 841 | .ErrorUnion => { |
| 834 | if (location != .Initializer) { | 842 | if (!location.isInitializer()) { |
| 835 | try writer.writeByte('('); | 843 | try writer.writeByte('('); |
| 836 | try dg.renderTypecast(writer, ty); | 844 | try dg.renderTypecast(writer, ty); |
| 837 | try writer.writeByte(')'); | 845 | try writer.writeByte(')'); |
| ... | @@ -844,7 +852,7 @@ pub const DeclGen = struct { | ... | @@ -844,7 +852,7 @@ pub const DeclGen = struct { |
| 844 | }); | 852 | }); |
| 845 | }, | 853 | }, |
| 846 | .Array, .Vector => { | 854 | .Array, .Vector => { |
| 847 | if (location != .Initializer) { | 855 | if (!location.isInitializer()) { |
| 848 | try writer.writeByte('('); | 856 | try writer.writeByte('('); |
| 849 | try dg.renderTypecast(writer, ty); | 857 | try dg.renderTypecast(writer, ty); |
| 850 | try writer.writeByte(')'); | 858 | try writer.writeByte(')'); |
| ... | @@ -899,7 +907,7 @@ pub const DeclGen = struct { | ... | @@ -899,7 +907,7 @@ pub const DeclGen = struct { |
| 899 | .decl_ref_mut, | 907 | .decl_ref_mut, |
| 900 | .decl_ref, | 908 | .decl_ref, |
| 901 | => try dg.renderParentPtr(writer, val, ty), | 909 | => try dg.renderParentPtr(writer, val, ty), |
| 902 | else => try writer.print("{}", .{try dg.fmtIntLiteral(ty, val)}), | 910 | else => try writer.print("{}", .{try dg.fmtIntLiteralLoc(ty, val, location)}), |
| 903 | }, | 911 | }, |
| 904 | .Float => { | 912 | .Float => { |
| 905 | const bits = ty.floatBits(target); | 913 | const bits = ty.floatBits(target); |
| ... | @@ -934,6 +942,7 @@ pub const DeclGen = struct { | ... | @@ -934,6 +942,7 @@ pub const DeclGen = struct { |
| 934 | try writer.writeAll("zig_cast_"); | 942 | try writer.writeAll("zig_cast_"); |
| 935 | try dg.renderTypeForBuiltinFnName(writer, ty); | 943 | try dg.renderTypeForBuiltinFnName(writer, ty); |
| 936 | try writer.writeByte(' '); | 944 | try writer.writeByte(' '); |
| | 945 | var empty = true; |
| 937 | if (std.math.isFinite(f128_val)) { | 946 | if (std.math.isFinite(f128_val)) { |
| 938 | try writer.writeAll("zig_as_"); | 947 | try writer.writeAll("zig_as_"); |
| 939 | try dg.renderTypeForBuiltinFnName(writer, ty); | 948 | try dg.renderTypeForBuiltinFnName(writer, ty); |
| ... | @@ -946,11 +955,14 @@ pub const DeclGen = struct { | ... | @@ -946,11 +955,14 @@ pub const DeclGen = struct { |
| 946 | 128 => try writer.print("{x}", .{f128_val}), | 955 | 128 => try writer.print("{x}", .{f128_val}), |
| 947 | else => unreachable, | 956 | else => unreachable, |
| 948 | } | 957 | } |
| 949 | } else { | 958 | try writer.writeAll(", "); |
| 950 | const operation = if (std.math.isSignalNan(f128_val)) | 959 | empty = false; |
| 951 | "nans" | 960 | } else if (location != .StaticInitializer) { |
| 952 | else if (std.math.isNan(f128_val)) | 961 | // isSignalNan is equivalent to isNan currently, and MSVC doens't have nans, so prefer nan |
| | 962 | const operation = if (std.math.isNan(f128_val)) |
| 953 | "nan" | 963 | "nan" |
| | 964 | else if (std.math.isSignalNan(f128_val)) |
| | 965 | "nans" |
| 954 | else if (std.math.isInf(f128_val)) | 966 | else if (std.math.isInf(f128_val)) |
| 955 | "inf" | 967 | "inf" |
| 956 | else | 968 | else |
| ... | @@ -973,8 +985,13 @@ pub const DeclGen = struct { | ... | @@ -973,8 +985,13 @@ pub const DeclGen = struct { |
| 973 | 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}), | 985 | 128 => try writer.print("\"0x{x}\"", .{@bitCast(u128, f128_val)}), |
| 974 | else => unreachable, | 986 | else => unreachable, |
| 975 | }; | 987 | }; |
| | 988 | try writer.writeAll(", "); |
| | 989 | empty = false; |
| | 990 | |
| 976 | } | 991 | } |
| 977 | return writer.print(", {x})", .{try dg.fmtIntLiteral(int_ty, int_val)}); | 992 | try writer.print("{x}", .{try dg.fmtIntLiteralLoc(int_ty, int_val, location)}); |
| | 993 | if (!empty) try writer.writeByte(')'); |
| | 994 | return; |
| 978 | }, | 995 | }, |
| 979 | .Pointer => switch (val.tag()) { | 996 | .Pointer => switch (val.tag()) { |
| 980 | .null_value, .zero => if (ty.isSlice()) { | 997 | .null_value, .zero => if (ty.isSlice()) { |
| ... | @@ -995,7 +1012,7 @@ pub const DeclGen = struct { | ... | @@ -995,7 +1012,7 @@ pub const DeclGen = struct { |
| 995 | return dg.renderDeclValue(writer, ty, val, decl); | 1012 | return dg.renderDeclValue(writer, ty, val, decl); |
| 996 | }, | 1013 | }, |
| 997 | .slice => { | 1014 | .slice => { |
| 998 | if (location != .Initializer) { | 1015 | if (!location.isInitializer()) { |
| 999 | try writer.writeByte('('); | 1016 | try writer.writeByte('('); |
| 1000 | try dg.renderTypecast(writer, ty); | 1017 | try dg.renderTypecast(writer, ty); |
| 1001 | try writer.writeByte(')'); | 1018 | try writer.writeByte(')'); |
| ... | @@ -1136,7 +1153,7 @@ pub const DeclGen = struct { | ... | @@ -1136,7 +1153,7 @@ pub const DeclGen = struct { |
| 1136 | return dg.renderValue(writer, payload_ty, payload_val, location); | 1153 | return dg.renderValue(writer, payload_ty, payload_val, location); |
| 1137 | } | 1154 | } |
| 1138 | | 1155 | |
| 1139 | if (location != .Initializer) { | 1156 | if (!location.isInitializer()) { |
| 1140 | try writer.writeByte('('); | 1157 | try writer.writeByte('('); |
| 1141 | try dg.renderTypecast(writer, ty); | 1158 | try dg.renderTypecast(writer, ty); |
| 1142 | try writer.writeByte(')'); | 1159 | try writer.writeByte(')'); |
| ... | @@ -1170,7 +1187,7 @@ pub const DeclGen = struct { | ... | @@ -1170,7 +1187,7 @@ pub const DeclGen = struct { |
| 1170 | return dg.renderValue(writer, error_ty, val, location); | 1187 | return dg.renderValue(writer, error_ty, val, location); |
| 1171 | } | 1188 | } |
| 1172 | | 1189 | |
| 1173 | if (location != .Initializer) { | 1190 | if (!location.isInitializer()) { |
| 1174 | try writer.writeByte('('); | 1191 | try writer.writeByte('('); |
| 1175 | try dg.renderTypecast(writer, ty); | 1192 | try dg.renderTypecast(writer, ty); |
| 1176 | try writer.writeByte(')'); | 1193 | try writer.writeByte(')'); |
| ... | @@ -1234,7 +1251,7 @@ pub const DeclGen = struct { | ... | @@ -1234,7 +1251,7 @@ pub const DeclGen = struct { |
| 1234 | .Auto, .Extern => { | 1251 | .Auto, .Extern => { |
| 1235 | const field_vals = val.castTag(.aggregate).?.data; | 1252 | const field_vals = val.castTag(.aggregate).?.data; |
| 1236 | | 1253 | |
| 1237 | if (location != .Initializer) { | 1254 | if (!location.isInitializer()) { |
| 1238 | try writer.writeByte('('); | 1255 | try writer.writeByte('('); |
| 1239 | try dg.renderTypecast(writer, ty); | 1256 | try dg.renderTypecast(writer, ty); |
| 1240 | try writer.writeByte(')'); | 1257 | try writer.writeByte(')'); |
| ... | @@ -1247,7 +1264,10 @@ pub const DeclGen = struct { | ... | @@ -1247,7 +1264,10 @@ pub const DeclGen = struct { |
| 1247 | if (!field_ty.hasRuntimeBits()) continue; | 1264 | if (!field_ty.hasRuntimeBits()) continue; |
| 1248 | | 1265 | |
| 1249 | if (!empty) try writer.writeByte(','); | 1266 | if (!empty) try writer.writeByte(','); |
| 1250 | try dg.renderValue(writer, field_ty, field_val, .Initializer); | 1267 | try dg.renderValue(writer, field_ty, field_val, switch (location) { |
| | 1268 | .StaticInitializer => .StaticInitializer, |
| | 1269 | else => .Initializer, |
| | 1270 | }); |
| 1251 | | 1271 | |
| 1252 | empty = false; | 1272 | empty = false; |
| 1253 | } | 1273 | } |
| ... | @@ -1345,7 +1365,7 @@ pub const DeclGen = struct { | ... | @@ -1345,7 +1365,7 @@ pub const DeclGen = struct { |
| 1345 | .Union => { | 1365 | .Union => { |
| 1346 | const union_obj = val.castTag(.@"union").?.data; | 1366 | const union_obj = val.castTag(.@"union").?.data; |
| 1347 | | 1367 | |
| 1348 | if (location != .Initializer) { | 1368 | if (!location.isInitializer()) { |
| 1349 | try writer.writeByte('('); | 1369 | try writer.writeByte('('); |
| 1350 | try dg.renderTypecast(writer, ty); | 1370 | try dg.renderTypecast(writer, ty); |
| 1351 | try writer.writeByte(')'); | 1371 | try writer.writeByte(')'); |
| ... | @@ -2561,6 +2581,24 @@ pub const DeclGen = struct { | ... | @@ -2561,6 +2581,24 @@ pub const DeclGen = struct { |
| 2561 | .mod = dg.module, | 2581 | .mod = dg.module, |
| 2562 | } }; | 2582 | } }; |
| 2563 | } | 2583 | } |
| | 2584 | |
| | 2585 | fn fmtIntLiteralLoc( |
| | 2586 | dg: *DeclGen, |
| | 2587 | ty: Type, |
| | 2588 | val: Value, |
| | 2589 | location: ValueRenderLocation, // TODO: Instead add this as optional arg to fmtIntLiteralLoc |
| | 2590 | ) !std.fmt.Formatter(formatIntLiteral) { |
| | 2591 | const int_info = ty.intInfo(dg.module.getTarget()); |
| | 2592 | const c_bits = toCIntBits(int_info.bits); |
| | 2593 | if (c_bits == null or c_bits.? > 128) |
| | 2594 | return dg.fail("TODO implement integer constants larger than 128 bits", .{}); |
| | 2595 | return std.fmt.Formatter(formatIntLiteral){ .data = .{ |
| | 2596 | .ty = ty, |
| | 2597 | .val = val, |
| | 2598 | .mod = dg.module, |
| | 2599 | .location = location |
| | 2600 | } }; |
| | 2601 | } |
| 2564 | }; | 2602 | }; |
| 2565 | | 2603 | |
| 2566 | pub fn genGlobalAsm(mod: *Module, code: *std.ArrayList(u8)) !void { | 2604 | pub fn genGlobalAsm(mod: *Module, code: *std.ArrayList(u8)) !void { |
| ... | @@ -2606,7 +2644,7 @@ pub fn genErrDecls(o: *Object) !void { | ... | @@ -2606,7 +2644,7 @@ pub fn genErrDecls(o: *Object) !void { |
| 2606 | try writer.writeAll("static "); | 2644 | try writer.writeAll("static "); |
| 2607 | try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .Const, 0, .Complete); | 2645 | try o.dg.renderTypeAndName(writer, name_ty, .{ .identifier = identifier }, .Const, 0, .Complete); |
| 2608 | try writer.writeAll(" = "); | 2646 | try writer.writeAll(" = "); |
| 2609 | try o.dg.renderValue(writer, name_ty, name_val, .Initializer); | 2647 | try o.dg.renderValue(writer, name_ty, name_val, .StaticInitializer); |
| 2610 | try writer.writeAll(";\n"); | 2648 | try writer.writeAll(";\n"); |
| 2611 | } | 2649 | } |
| 2612 | | 2650 | |
| ... | @@ -2777,7 +2815,7 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -2777,7 +2815,7 @@ pub fn genDecl(o: *Object) !void { |
| 2777 | if (variable.is_threadlocal) try w.writeAll("zig_threadlocal "); | 2815 | if (variable.is_threadlocal) try w.writeAll("zig_threadlocal "); |
| 2778 | try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete); | 2816 | try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete); |
| 2779 | try w.writeAll(" = "); | 2817 | try w.writeAll(" = "); |
| 2780 | try o.dg.renderValue(w, tv.ty, variable.init, .Initializer); | 2818 | try o.dg.renderValue(w, tv.ty, variable.init, .StaticInitializer); |
| 2781 | try w.writeByte(';'); | 2819 | try w.writeByte(';'); |
| 2782 | try o.indent_writer.insertNewline(); | 2820 | try o.indent_writer.insertNewline(); |
| 2783 | } else { | 2821 | } else { |
| ... | @@ -2794,7 +2832,7 @@ pub fn genDecl(o: *Object) !void { | ... | @@ -2794,7 +2832,7 @@ pub fn genDecl(o: *Object) !void { |
| 2794 | // https://github.com/ziglang/zig/issues/7582 | 2832 | // https://github.com/ziglang/zig/issues/7582 |
| 2795 | try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete); | 2833 | try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete); |
| 2796 | try writer.writeAll(" = "); | 2834 | try writer.writeAll(" = "); |
| 2797 | try o.dg.renderValue(writer, tv.ty, tv.val, .Initializer); | 2835 | try o.dg.renderValue(writer, tv.ty, tv.val, .StaticInitializer); |
| 2798 | try writer.writeAll(";\n"); | 2836 | try writer.writeAll(";\n"); |
| 2799 | } | 2837 | } |
| 2800 | } | 2838 | } |
| ... | @@ -7027,7 +7065,7 @@ fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 { | ... | @@ -7027,7 +7065,7 @@ fn compilerRtAbbrev(ty: Type, target: std.Target) []const u8 { |
| 7027 | } | 7065 | } |
| 7028 | | 7066 | |
| 7029 | fn StringLiteral(comptime WriterType: type) type { | 7067 | fn StringLiteral(comptime WriterType: type) type { |
| 7030 | // msvc has a length limit of 16380 per string literal (before concatenation) | 7068 | // MSVC has a length limit of 16380 per string literal (before concatenation) |
| 7031 | const max_char_len = 4; | 7069 | const max_char_len = 4; |
| 7032 | const max_len = 16380 - max_char_len; | 7070 | const max_len = 16380 - max_char_len; |
| 7033 | | 7071 | |
| ... | @@ -7117,6 +7155,7 @@ const FormatIntLiteralContext = struct { | ... | @@ -7117,6 +7155,7 @@ const FormatIntLiteralContext = struct { |
| 7117 | ty: Type, | 7155 | ty: Type, |
| 7118 | val: Value, | 7156 | val: Value, |
| 7119 | mod: *Module, | 7157 | mod: *Module, |
| | 7158 | location: ?ValueRenderLocation = null |
| 7120 | }; | 7159 | }; |
| 7121 | fn formatIntLiteral( | 7160 | fn formatIntLiteral( |
| 7122 | data: FormatIntLiteralContext, | 7161 | data: FormatIntLiteralContext, |
| ... | @@ -7188,6 +7227,7 @@ fn formatIntLiteral( | ... | @@ -7188,6 +7227,7 @@ fn formatIntLiteral( |
| 7188 | if (!int.positive) { | 7227 | if (!int.positive) { |
| 7189 | if (c_bits > 64) { | 7228 | if (c_bits > 64) { |
| 7190 | // TODO: Could use negate function instead? | 7229 | // TODO: Could use negate function instead? |
| | 7230 | // TODO: Use fmtIntLiteral for 0? |
| 7191 | try writer.print("zig_sub_{c}{d}(zig_as_{c}{d}(0, 0), ", .{ signAbbrev(int_info.signedness), c_bits, signAbbrev(int_info.signedness), c_bits }); | 7231 | try writer.print("zig_sub_{c}{d}(zig_as_{c}{d}(0, 0), ", .{ signAbbrev(int_info.signedness), c_bits, signAbbrev(int_info.signedness), c_bits }); |
| 7192 | } else { | 7232 | } else { |
| 7193 | try writer.writeByte('-'); | 7233 | try writer.writeByte('-'); |
| ... | @@ -7196,7 +7236,14 @@ fn formatIntLiteral( | ... | @@ -7196,7 +7236,14 @@ fn formatIntLiteral( |
| 7196 | | 7236 | |
| 7197 | switch (data.ty.tag()) { | 7237 | switch (data.ty.tag()) { |
| 7198 | .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {}, | 7238 | .c_short, .c_ushort, .c_int, .c_uint, .c_long, .c_ulong, .c_longlong, .c_ulonglong => {}, |
| 7199 | else => try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }), | 7239 | else => { |
| | 7240 | if (int_info.bits > 64 and data.location != null and data.location.? == .StaticInitializer) { |
| | 7241 | // MSVC treats casting the struct initializer as not constant (C2099), so an alternate form is used in global initializers |
| | 7242 | try writer.print("zig_as_init_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }); |
| | 7243 | } else { |
| | 7244 | try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }); |
| | 7245 | } |
| | 7246 | } |
| 7200 | } | 7247 | } |
| 7201 | | 7248 | |
| 7202 | const limbs_count_64 = @divExact(64, @bitSizeOf(BigIntLimb)); | 7249 | const limbs_count_64 = @divExact(64, @bitSizeOf(BigIntLimb)); |