authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2022-12-12 02:57:57-05:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-01-01 16:44:28-05:00
log7f3bc45772d6af33e0e663ba534eba5653792843
treeabcb77b390eecffcc1822de31d64c5773429d8e6
parent4fe71977e0c2bec28b4cb8015d59ce837dfc80cb

cbe: nan builtins on msvc, fixup C2099 errors in static initializers

- Map the __builtin_nan(f|l)? functions to nan(f|l)? on msvc - MSVC throws C2099 when initializing a struct with cast syntax in a global initializer. Added zig_as_init_ to handle this case, and generate it only in static initializers for > 64 bit ints. - Change float initialization to emit the integer representation in global initializers to avoid C2099 caused by calling nan.

2 files changed, 81 insertions(+), 24 deletions(-)

lib/zig.h+10
...@@ -1151,6 +1151,8 @@ typedef signed __int128 zig_i128;...@@ -1151,6 +1151,8 @@ typedef signed __int128 zig_i128;
11511151
1152#define zig_as_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))1152#define zig_as_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
1153#define zig_as_i128(hi, lo) ((zig_i128)zig_as_u128(hi, lo))1153#define zig_as_i128(hi, lo) ((zig_i128)zig_as_u128(hi, lo))
1154#define zig_as_init_u128(hi, lo) zig_as_u128(hi, lo)
1155#define zig_as_init_i128(hi, lo) zig_as_i128(hi, lo)
1154#define zig_hi_u128(val) ((zig_u64)((val) >> 64))1156#define zig_hi_u128(val) ((zig_u64)((val) >> 64))
1155#define zig_lo_u128(val) ((zig_u64)((val) >> 0))1157#define zig_lo_u128(val) ((zig_u64)((val) >> 0))
1156#define zig_hi_i128(val) ((zig_i64)((val) >> 64))1158#define zig_hi_i128(val) ((zig_i64)((val) >> 64))
...@@ -1178,6 +1180,8 @@ typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128;...@@ -1178,6 +1180,8 @@ typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128;
11781180
1179#define zig_as_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })1181#define zig_as_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
1180#define zig_as_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })1182#define zig_as_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
1183#define zig_as_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1184#define zig_as_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1181#define zig_hi_u128(val) ((val).hi)1185#define zig_hi_u128(val) ((val).hi)
1182#define zig_lo_u128(val) ((val).lo)1186#define zig_lo_u128(val) ((val).lo)
1183#define zig_hi_i128(val) ((val).hi)1187#define zig_hi_i128(val) ((val).hi)
...@@ -1631,6 +1635,12 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {...@@ -1631,6 +1635,12 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {
16311635
1632/* ========================= Floating Point Support ========================= */1636/* ========================= Floating Point Support ========================= */
16331637
1638#if _MSC_VER
1639#define __builtin_nan(str) nan(str)
1640#define __builtin_nanf(str) nanf(str)
1641#define __builtin_nanl(str) nanl(str)
1642#endif
1643
1634#define zig_has_f16 11644#define zig_has_f16 1
1635#define zig_bitSizeOf_f16 161645#define zig_bitSizeOf_f16 16
1636#define zig_libc_name_f16(name) __##name##h1646#define zig_libc_name_f16(name) __##name##h
src/codegen/c.zig+71-24
...@@ -90,7 +90,15 @@ const FormatTypeAsCIdentContext = struct {...@@ -90,7 +90,15 @@ const FormatTypeAsCIdentContext = struct {
90const ValueRenderLocation = enum {90const 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};
95103
96const BuiltinInfo = enum {104const 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 }
772780
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 else968 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 }
11381155
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 }
11721189
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;
12361253
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;
12481265
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 });
12511271
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;
13471367
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};
25652603
2566pub fn genGlobalAsm(mod: *Module, code: *std.ArrayList(u8)) !void {2604pub 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 }
26122650
...@@ -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/75822832 // 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}
70287066
7029fn StringLiteral(comptime WriterType: type) type {7067fn 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;
70337071
...@@ -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};
7121fn formatIntLiteral(7160fn 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(
71967236
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 }
72017248
7202 const limbs_count_64 = @divExact(64, @bitSizeOf(BigIntLimb));7249 const limbs_count_64 = @divExact(64, @bitSizeOf(BigIntLimb));