| ... | @@ -711,6 +711,10 @@ pub const DeclGen = struct { | ... | @@ -711,6 +711,10 @@ pub const DeclGen = struct { |
| 711 | val = rt.data; | 711 | val = rt.data; |
| 712 | } | 712 | } |
| 713 | const target = dg.module.getTarget(); | 713 | const target = dg.module.getTarget(); |
| | 714 | const initializer_type: ValueRenderLocation = switch (location) { |
| | 715 | .StaticInitializer => .StaticInitializer, |
| | 716 | else => .Initializer, |
| | 717 | }; |
| 714 | | 718 | |
| 715 | const safety_on = switch (dg.module.optimizeMode()) { | 719 | const safety_on = switch (dg.module.optimizeMode()) { |
| 716 | .Debug, .ReleaseSafe => true, | 720 | .Debug, .ReleaseSafe => true, |
| ... | @@ -785,9 +789,9 @@ pub const DeclGen = struct { | ... | @@ -785,9 +789,9 @@ pub const DeclGen = struct { |
| 785 | } | 789 | } |
| 786 | | 790 | |
| 787 | try writer.writeAll("{ .payload = "); | 791 | try writer.writeAll("{ .payload = "); |
| 788 | try dg.renderValue(writer, payload_ty, val, .Initializer); | 792 | try dg.renderValue(writer, payload_ty, val, initializer_type); |
| 789 | try writer.writeAll(", .is_null = "); | 793 | try writer.writeAll(", .is_null = "); |
| 790 | try dg.renderValue(writer, Type.bool, val, .Initializer); | 794 | try dg.renderValue(writer, Type.bool, val, initializer_type); |
| 791 | return writer.writeAll(" }"); | 795 | return writer.writeAll(" }"); |
| 792 | }, | 796 | }, |
| 793 | .Struct => switch (ty.containerLayout()) { | 797 | .Struct => switch (ty.containerLayout()) { |
| ... | @@ -804,7 +808,7 @@ pub const DeclGen = struct { | ... | @@ -804,7 +808,7 @@ pub const DeclGen = struct { |
| 804 | if (!field.ty.hasRuntimeBits()) continue; | 808 | if (!field.ty.hasRuntimeBits()) continue; |
| 805 | | 809 | |
| 806 | if (!empty) try writer.writeByte(','); | 810 | if (!empty) try writer.writeByte(','); |
| 807 | try dg.renderValue(writer, field.ty, val, .Initializer); | 811 | try dg.renderValue(writer, field.ty, val, initializer_type); |
| 808 | | 812 | |
| 809 | empty = false; | 813 | empty = false; |
| 810 | } | 814 | } |
| ... | @@ -825,14 +829,14 @@ pub const DeclGen = struct { | ... | @@ -825,14 +829,14 @@ pub const DeclGen = struct { |
| 825 | const layout = ty.unionGetLayout(target); | 829 | const layout = ty.unionGetLayout(target); |
| 826 | if (layout.tag_size != 0) { | 830 | if (layout.tag_size != 0) { |
| 827 | try writer.writeAll(" .tag = "); | 831 | try writer.writeAll(" .tag = "); |
| 828 | try dg.renderValue(writer, tag_ty, val, .Initializer); | 832 | try dg.renderValue(writer, tag_ty, val, initializer_type); |
| 829 | try writer.writeByte(','); | 833 | try writer.writeByte(','); |
| 830 | } | 834 | } |
| 831 | try writer.writeAll(" .payload = {"); | 835 | try writer.writeAll(" .payload = {"); |
| 832 | } | 836 | } |
| 833 | for (ty.unionFields().values()) |field| { | 837 | for (ty.unionFields().values()) |field| { |
| 834 | if (!field.ty.hasRuntimeBits()) continue; | 838 | if (!field.ty.hasRuntimeBits()) continue; |
| 835 | try dg.renderValue(writer, field.ty, val, .Initializer); | 839 | try dg.renderValue(writer, field.ty, val, initializer_type); |
| 836 | break; | 840 | break; |
| 837 | } else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)}); | 841 | } else try writer.print("{x}", .{try dg.fmtIntLiteral(Type.u8, Value.undef)}); |
| 838 | if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}'); | 842 | if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}'); |
| ... | @@ -846,7 +850,7 @@ pub const DeclGen = struct { | ... | @@ -846,7 +850,7 @@ pub const DeclGen = struct { |
| 846 | } | 850 | } |
| 847 | | 851 | |
| 848 | try writer.writeAll("{ .payload = "); | 852 | try writer.writeAll("{ .payload = "); |
| 849 | try dg.renderValue(writer, ty.errorUnionPayload(), val, .Initializer); | 853 | try dg.renderValue(writer, ty.errorUnionPayload(), val, initializer_type); |
| 850 | return writer.print(", .error = {x} }}", .{ | 854 | return writer.print(", .error = {x} }}", .{ |
| 851 | try dg.fmtIntLiteral(ty.errorUnionSet(), val), | 855 | try dg.fmtIntLiteral(ty.errorUnionSet(), val), |
| 852 | }); | 856 | }); |
| ... | @@ -873,7 +877,7 @@ pub const DeclGen = struct { | ... | @@ -873,7 +877,7 @@ pub const DeclGen = struct { |
| 873 | var index: usize = 0; | 877 | var index: usize = 0; |
| 874 | while (index < c_len) : (index += 1) { | 878 | while (index < c_len) : (index += 1) { |
| 875 | if (index > 0) try writer.writeAll(", "); | 879 | if (index > 0) try writer.writeAll(", "); |
| 876 | try dg.renderValue(writer, ty.childType(), val, .Initializer); | 880 | try dg.renderValue(writer, ty.childType(), val, initializer_type); |
| 877 | } | 881 | } |
| 878 | return writer.writeByte('}'); | 882 | return writer.writeByte('}'); |
| 879 | } | 883 | } |
| ... | @@ -957,7 +961,7 @@ pub const DeclGen = struct { | ... | @@ -957,7 +961,7 @@ pub const DeclGen = struct { |
| 957 | } | 961 | } |
| 958 | try writer.writeAll(", "); | 962 | try writer.writeAll(", "); |
| 959 | empty = false; | 963 | empty = false; |
| 960 | } else if (location != .StaticInitializer) { | 964 | } else { |
| 961 | // isSignalNan is equivalent to isNan currently, and MSVC doens't have nans, so prefer nan | 965 | // isSignalNan is equivalent to isNan currently, and MSVC doens't have nans, so prefer nan |
| 962 | const operation = if (std.math.isNan(f128_val)) | 966 | const operation = if (std.math.isNan(f128_val)) |
| 963 | "nan" | 967 | "nan" |
| ... | @@ -968,7 +972,19 @@ pub const DeclGen = struct { | ... | @@ -968,7 +972,19 @@ pub const DeclGen = struct { |
| 968 | else | 972 | else |
| 969 | unreachable; | 973 | unreachable; |
| 970 | | 974 | |
| | 975 | if (location == .StaticInitializer) { |
| | 976 | if (!std.math.isNan(f128_val) and std.math.isSignalNan(f128_val)) |
| | 977 | return dg.fail("TODO: C backend: implement nans rendering in static initializers", .{}); |
| | 978 | |
| | 979 | // MSVC doesn't have a way to define a custom or signaling NaN value in a constant expression |
| | 980 | |
| | 981 | // TODO: Re-enable this check, otherwise we're writing qnan bit patterns on msvc incorrectly |
| | 982 | // if (std.math.isNan(f128_val) and f128_val != std.math.qnan_f128) |
| | 983 | // return dg.fail("Only quiet nans are supported in global variable initializers", .{}); |
| | 984 | } |
| | 985 | |
| 971 | try writer.writeAll("zig_as_special_"); | 986 | try writer.writeAll("zig_as_special_"); |
| | 987 | if (location == .StaticInitializer) try writer.writeAll("constant_"); |
| 972 | try dg.renderTypeForBuiltinFnName(writer, ty); | 988 | try dg.renderTypeForBuiltinFnName(writer, ty); |
| 973 | try writer.writeByte('('); | 989 | try writer.writeByte('('); |
| 974 | if (std.math.signbit(f128_val)) try writer.writeByte('-'); | 990 | if (std.math.signbit(f128_val)) try writer.writeByte('-'); |
| ... | @@ -987,7 +1003,6 @@ pub const DeclGen = struct { | ... | @@ -987,7 +1003,6 @@ pub const DeclGen = struct { |
| 987 | }; | 1003 | }; |
| 988 | try writer.writeAll(", "); | 1004 | try writer.writeAll(", "); |
| 989 | empty = false; | 1005 | empty = false; |
| 990 | | | |
| 991 | } | 1006 | } |
| 992 | try writer.print("{x}", .{try dg.fmtIntLiteralLoc(int_ty, int_val, location)}); | 1007 | try writer.print("{x}", .{try dg.fmtIntLiteralLoc(int_ty, int_val, location)}); |
| 993 | if (!empty) try writer.writeByte(')'); | 1008 | if (!empty) try writer.writeByte(')'); |
| ... | @@ -1022,9 +1037,9 @@ pub const DeclGen = struct { | ... | @@ -1022,9 +1037,9 @@ pub const DeclGen = struct { |
| 1022 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 1037 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1023 | | 1038 | |
| 1024 | try writer.writeByte('{'); | 1039 | try writer.writeByte('{'); |
| 1025 | try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, .Initializer); | 1040 | try dg.renderValue(writer, ty.slicePtrFieldType(&buf), slice.ptr, initializer_type); |
| 1026 | try writer.writeAll(", "); | 1041 | try writer.writeAll(", "); |
| 1027 | try dg.renderValue(writer, Type.usize, slice.len, .Initializer); | 1042 | try dg.renderValue(writer, Type.usize, slice.len, initializer_type); |
| 1028 | try writer.writeByte('}'); | 1043 | try writer.writeByte('}'); |
| 1029 | }, | 1044 | }, |
| 1030 | .function => { | 1045 | .function => { |
| ... | @@ -1062,7 +1077,7 @@ pub const DeclGen = struct { | ... | @@ -1062,7 +1077,7 @@ pub const DeclGen = struct { |
| 1062 | try writer.writeByte('{'); | 1077 | try writer.writeByte('{'); |
| 1063 | const ai = ty.arrayInfo(); | 1078 | const ai = ty.arrayInfo(); |
| 1064 | if (ai.sentinel) |s| { | 1079 | if (ai.sentinel) |s| { |
| 1065 | try dg.renderValue(writer, ai.elem_type, s, .Initializer); | 1080 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); |
| 1066 | } else { | 1081 | } else { |
| 1067 | try writer.writeByte('0'); | 1082 | try writer.writeByte('0'); |
| 1068 | } | 1083 | } |
| ... | @@ -1085,6 +1100,7 @@ pub const DeclGen = struct { | ... | @@ -1085,6 +1100,7 @@ pub const DeclGen = struct { |
| 1085 | // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal | 1100 | // MSVC throws C2078 if an array of size 65536 or greater is initialized with a string literal |
| 1086 | const max_string_initializer_len = 65535; | 1101 | const max_string_initializer_len = 65535; |
| 1087 | | 1102 | |
| | 1103 | |
| 1088 | const ai = ty.arrayInfo(); | 1104 | const ai = ty.arrayInfo(); |
| 1089 | if (ai.elem_type.eql(Type.u8, dg.module)) { | 1105 | if (ai.elem_type.eql(Type.u8, dg.module)) { |
| 1090 | if (ai.len <= max_string_initializer_len) { | 1106 | if (ai.len <= max_string_initializer_len) { |
| ... | @@ -1112,7 +1128,7 @@ pub const DeclGen = struct { | ... | @@ -1112,7 +1128,7 @@ pub const DeclGen = struct { |
| 1112 | } | 1128 | } |
| 1113 | if (ai.sentinel) |s| { | 1129 | if (ai.sentinel) |s| { |
| 1114 | if (index != 0) try writer.writeByte(','); | 1130 | if (index != 0) try writer.writeByte(','); |
| 1115 | try dg.renderValue(writer, ai.elem_type, s, .Initializer); | 1131 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); |
| 1116 | } | 1132 | } |
| 1117 | try writer.writeByte('}'); | 1133 | try writer.writeByte('}'); |
| 1118 | } | 1134 | } |
| ... | @@ -1122,11 +1138,11 @@ pub const DeclGen = struct { | ... | @@ -1122,11 +1138,11 @@ pub const DeclGen = struct { |
| 1122 | while (index < ai.len) : (index += 1) { | 1138 | while (index < ai.len) : (index += 1) { |
| 1123 | if (index != 0) try writer.writeByte(','); | 1139 | if (index != 0) try writer.writeByte(','); |
| 1124 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); | 1140 | const elem_val = try val.elemValue(dg.module, arena_allocator, index); |
| 1125 | try dg.renderValue(writer, ai.elem_type, elem_val, .Initializer); | 1141 | try dg.renderValue(writer, ai.elem_type, elem_val, initializer_type); |
| 1126 | } | 1142 | } |
| 1127 | if (ai.sentinel) |s| { | 1143 | if (ai.sentinel) |s| { |
| 1128 | if (index != 0) try writer.writeByte(','); | 1144 | if (index != 0) try writer.writeByte(','); |
| 1129 | try dg.renderValue(writer, ai.elem_type, s, .Initializer); | 1145 | try dg.renderValue(writer, ai.elem_type, s, initializer_type); |
| 1130 | } | 1146 | } |
| 1131 | try writer.writeByte('}'); | 1147 | try writer.writeByte('}'); |
| 1132 | } | 1148 | } |
| ... | @@ -1162,9 +1178,9 @@ pub const DeclGen = struct { | ... | @@ -1162,9 +1178,9 @@ pub const DeclGen = struct { |
| 1162 | const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else Value.undef; | 1178 | const payload_val = if (val.castTag(.opt_payload)) |pl| pl.data else Value.undef; |
| 1163 | | 1179 | |
| 1164 | try writer.writeAll("{ .payload = "); | 1180 | try writer.writeAll("{ .payload = "); |
| 1165 | try dg.renderValue(writer, payload_ty, payload_val, .Initializer); | 1181 | try dg.renderValue(writer, payload_ty, payload_val, initializer_type); |
| 1166 | try writer.writeAll(", .is_null = "); | 1182 | try writer.writeAll(", .is_null = "); |
| 1167 | try dg.renderValue(writer, Type.bool, is_null_val, .Initializer); | 1183 | try dg.renderValue(writer, Type.bool, is_null_val, initializer_type); |
| 1168 | try writer.writeAll(" }"); | 1184 | try writer.writeAll(" }"); |
| 1169 | }, | 1185 | }, |
| 1170 | .ErrorSet => { | 1186 | .ErrorSet => { |
| ... | @@ -1197,9 +1213,9 @@ pub const DeclGen = struct { | ... | @@ -1197,9 +1213,9 @@ pub const DeclGen = struct { |
| 1197 | const error_val = if (val.errorUnionIsPayload()) Value.zero else val; | 1213 | const error_val = if (val.errorUnionIsPayload()) Value.zero else val; |
| 1198 | | 1214 | |
| 1199 | try writer.writeAll("{ .payload = "); | 1215 | try writer.writeAll("{ .payload = "); |
| 1200 | try dg.renderValue(writer, payload_ty, payload_val, .Initializer); | 1216 | try dg.renderValue(writer, payload_ty, payload_val, initializer_type); |
| 1201 | try writer.writeAll(", .error = "); | 1217 | try writer.writeAll(", .error = "); |
| 1202 | try dg.renderValue(writer, error_ty, error_val, .Initializer); | 1218 | try dg.renderValue(writer, error_ty, error_val, initializer_type); |
| 1203 | try writer.writeAll(" }"); | 1219 | try writer.writeAll(" }"); |
| 1204 | }, | 1220 | }, |
| 1205 | .Enum => { | 1221 | .Enum => { |
| ... | @@ -1264,10 +1280,7 @@ pub const DeclGen = struct { | ... | @@ -1264,10 +1280,7 @@ pub const DeclGen = struct { |
| 1264 | if (!field_ty.hasRuntimeBits()) continue; | 1280 | if (!field_ty.hasRuntimeBits()) continue; |
| 1265 | | 1281 | |
| 1266 | if (!empty) try writer.writeByte(','); | 1282 | if (!empty) try writer.writeByte(','); |
| 1267 | try dg.renderValue(writer, field_ty, field_val, switch (location) { | 1283 | try dg.renderValue(writer, field_ty, field_val, initializer_type); |
| 1268 | .StaticInitializer => .StaticInitializer, | | |
| 1269 | else => .Initializer, | | |
| 1270 | }); | | |
| 1271 | | 1284 | |
| 1272 | empty = false; | 1285 | empty = false; |
| 1273 | } | 1286 | } |
| ... | @@ -1297,7 +1310,7 @@ pub const DeclGen = struct { | ... | @@ -1297,7 +1310,7 @@ pub const DeclGen = struct { |
| 1297 | | 1310 | |
| 1298 | if (eff_num_fields == 0) { | 1311 | if (eff_num_fields == 0) { |
| 1299 | try writer.writeByte('('); | 1312 | try writer.writeByte('('); |
| 1300 | try dg.renderValue(writer, ty, Value.undef, .Initializer); | 1313 | try dg.renderValue(writer, ty, Value.undef, initializer_type); |
| 1301 | try writer.writeByte(')'); | 1314 | try writer.writeByte(')'); |
| 1302 | } else if (ty.bitSize(target) > 64) { | 1315 | } else if (ty.bitSize(target) > 64) { |
| 1303 | // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off)) | 1316 | // zig_or_u128(zig_or_u128(zig_shl_u128(a, a_off), zig_shl_u128(b, b_off)), zig_shl_u128(c, c_off)) |
| ... | @@ -1385,7 +1398,7 @@ pub const DeclGen = struct { | ... | @@ -1385,7 +1398,7 @@ pub const DeclGen = struct { |
| 1385 | try dg.renderTypecast(writer, ty); | 1398 | try dg.renderTypecast(writer, ty); |
| 1386 | try writer.writeByte(')'); | 1399 | try writer.writeByte(')'); |
| 1387 | } | 1400 | } |
| 1388 | try dg.renderValue(writer, field_ty, union_obj.val, .Initializer); | 1401 | try dg.renderValue(writer, field_ty, union_obj.val, initializer_type); |
| 1389 | } else { | 1402 | } else { |
| 1390 | try writer.writeAll("0"); | 1403 | try writer.writeAll("0"); |
| 1391 | } | 1404 | } |
| ... | @@ -1397,7 +1410,7 @@ pub const DeclGen = struct { | ... | @@ -1397,7 +1410,7 @@ pub const DeclGen = struct { |
| 1397 | const layout = ty.unionGetLayout(target); | 1410 | const layout = ty.unionGetLayout(target); |
| 1398 | if (layout.tag_size != 0) { | 1411 | if (layout.tag_size != 0) { |
| 1399 | try writer.writeAll(".tag = "); | 1412 | try writer.writeAll(".tag = "); |
| 1400 | try dg.renderValue(writer, tag_ty, union_obj.tag, .Initializer); | 1413 | try dg.renderValue(writer, tag_ty, union_obj.tag, initializer_type); |
| 1401 | try writer.writeAll(", "); | 1414 | try writer.writeAll(", "); |
| 1402 | } | 1415 | } |
| 1403 | try writer.writeAll(".payload = {"); | 1416 | try writer.writeAll(".payload = {"); |
| ... | @@ -1406,11 +1419,11 @@ pub const DeclGen = struct { | ... | @@ -1406,11 +1419,11 @@ pub const DeclGen = struct { |
| 1406 | var it = ty.unionFields().iterator(); | 1419 | var it = ty.unionFields().iterator(); |
| 1407 | if (field_ty.hasRuntimeBits()) { | 1420 | if (field_ty.hasRuntimeBits()) { |
| 1408 | try writer.print(".{ } = ", .{fmtIdent(field_name)}); | 1421 | try writer.print(".{ } = ", .{fmtIdent(field_name)}); |
| 1409 | try dg.renderValue(writer, field_ty, union_obj.val, .Initializer); | 1422 | try dg.renderValue(writer, field_ty, union_obj.val, initializer_type); |
| 1410 | } else while (it.next()) |field| { | 1423 | } else while (it.next()) |field| { |
| 1411 | if (!field.value_ptr.ty.hasRuntimeBits()) continue; | 1424 | if (!field.value_ptr.ty.hasRuntimeBits()) continue; |
| 1412 | try writer.print(".{ } = ", .{fmtIdent(field.key_ptr.*)}); | 1425 | try writer.print(".{ } = ", .{fmtIdent(field.key_ptr.*)}); |
| 1413 | try dg.renderValue(writer, field.value_ptr.ty, Value.undef, .Initializer); | 1426 | try dg.renderValue(writer, field.value_ptr.ty, Value.undef, initializer_type); |
| 1414 | break; | 1427 | break; |
| 1415 | } else try writer.writeAll(".empty_union = 0"); | 1428 | } else try writer.writeAll(".empty_union = 0"); |
| 1416 | if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}'); | 1429 | if (ty.unionTagTypeSafety()) |_| try writer.writeByte('}'); |
| ... | @@ -7239,7 +7252,7 @@ fn formatIntLiteral( | ... | @@ -7239,7 +7252,7 @@ fn formatIntLiteral( |
| 7239 | else => { | 7252 | else => { |
| 7240 | if (int_info.bits > 64 and data.location != null and data.location.? == .StaticInitializer) { | 7253 | 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 | 7254 | // 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 }); | 7255 | try writer.print("zig_as_constant_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }); |
| 7243 | } else { | 7256 | } else { |
| 7244 | try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }); | 7257 | try writer.print("zig_as_{c}{d}(", .{ signAbbrev(int_info.signedness), c_bits }); |
| 7245 | } | 7258 | } |