authorgravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2022-12-13 01:19:21-05:00
committergravatar for kcbanner@gmail.comCasey Banner <kcbanner@gmail.com> 2023-01-01 16:44:28-05:00
log7fb3683c32fc24d12452f49e0c1639531e57c47d
tree0b9e38fd34be870ba2eb1e50147a58ec81709fd5
parent7f3bc45772d6af33e0e663ba534eba5653792843

cbe: more msvc compatibility work

- Add .StaticInitializer to ValueRenderLocation to indicate that the emitted values must be constant expressions (no function calls, struct casting). - Add new path for special float types (nan, inf) that works in constant expressions - Implement windows.teb() using a syscall for .stage2_c because x64 MSVC doesn't support any kind of inline asm

3 files changed, 146 insertions(+), 42 deletions(-)

lib/std/os/windows.zig+39-4
...@@ -1782,10 +1782,30 @@ pub fn teb() *TEB {...@@ -1782,10 +1782,30 @@ pub fn teb() *TEB {
1782 \\ movl %%fs:0x18, %[ptr]1782 \\ movl %%fs:0x18, %[ptr]
1783 : [ptr] "=r" (-> *TEB),1783 : [ptr] "=r" (-> *TEB),
1784 ),1784 ),
1785 .x86_64 => asm volatile (1785 .x86_64 => blk: {
1786 \\ movq %%gs:0x30, %[ptr]1786 if (builtin.zig_backend == .stage2_c) {
1787 : [ptr] "=r" (-> *TEB),1787 // TODO: __asm is not available on x64 MSVC. This is a workaround
1788 ),1788 // until an intrinsic to read the gs register is available
1789 var thread_information: THREAD_BASIC_INFORMATION = undefined;
1790 const result = ntdll.NtQueryInformationThread(
1791 kernel32.GetCurrentThread(),
1792 .ThreadBasicInformation,
1793 &thread_information,
1794 @sizeOf(THREAD_BASIC_INFORMATION),
1795 null);
1796
1797 if (result == .SUCCESS) {
1798 break :blk @ptrCast(*TEB, @alignCast(@alignOf(TEB), thread_information.TebBaseAddress));
1799 } else {
1800 unexpectedStatus(result) catch unreachable;
1801 }
1802 } else {
1803 break :blk asm volatile (
1804 \\ movq %%gs:0x30, %[ptr]
1805 : [ptr] "=r" (-> *TEB),
1806 );
1807 }
1808 },
1789 .aarch64 => asm volatile (1809 .aarch64 => asm volatile (
1790 \\ mov %[ptr], x181810 \\ mov %[ptr], x18
1791 : [ptr] "=r" (-> *TEB),1811 : [ptr] "=r" (-> *TEB),
...@@ -3455,6 +3475,21 @@ pub const ASSEMBLY_STORAGE_MAP = opaque {};...@@ -3455,6 +3475,21 @@ pub const ASSEMBLY_STORAGE_MAP = opaque {};
3455pub const FLS_CALLBACK_INFO = opaque {};3475pub const FLS_CALLBACK_INFO = opaque {};
3456pub const RTL_BITMAP = opaque {};3476pub const RTL_BITMAP = opaque {};
3457pub const KAFFINITY = usize;3477pub const KAFFINITY = usize;
3478pub const KPRIORITY = i32;
3479
3480pub const CLIENT_ID = extern struct {
3481 UniqueProcess: HANDLE,
3482 UniqueThread: HANDLE,
3483};
3484
3485pub const THREAD_BASIC_INFORMATION = extern struct {
3486 ExitStatus: NTSTATUS,
3487 TebBaseAddress: PVOID,
3488 ClientId: CLIENT_ID,
3489 AffinityMask: KAFFINITY,
3490 Priority: KPRIORITY,
3491 BasePriority: KPRIORITY,
3492};
34583493
3459pub const TEB = extern struct {3494pub const TEB = extern struct {
3460 Reserved1: [12]PVOID,3495 Reserved1: [12]PVOID,
lib/zig.h+65-9
...@@ -1151,8 +1151,8 @@ typedef signed __int128 zig_i128;...@@ -1151,8 +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)1154#define zig_as_constant_u128(hi, lo) zig_as_u128(hi, lo)
1155#define zig_as_init_i128(hi, lo) zig_as_i128(hi, lo)1155#define zig_as_constant_i128(hi, lo) zig_as_i128(hi, lo)
1156#define zig_hi_u128(val) ((zig_u64)((val) >> 64))1156#define zig_hi_u128(val) ((zig_u64)((val) >> 64))
1157#define zig_lo_u128(val) ((zig_u64)((val) >> 0))1157#define zig_lo_u128(val) ((zig_u64)((val) >> 0))
1158#define zig_hi_i128(val) ((zig_i64)((val) >> 64))1158#define zig_hi_i128(val) ((zig_i64)((val) >> 64))
...@@ -1180,8 +1180,8 @@ typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128;...@@ -1180,8 +1180,8 @@ typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128;
11801180
1181#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) })
1182#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) }1183#define zig_as_constant_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1184#define zig_as_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }1184#define zig_as_constant_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
1185#define zig_hi_u128(val) ((val).hi)1185#define zig_hi_u128(val) ((val).hi)
1186#define zig_lo_u128(val) ((val).lo)1186#define zig_lo_u128(val) ((val).lo)
1187#define zig_hi_i128(val) ((val).hi)1187#define zig_hi_i128(val) ((val).hi)
...@@ -1342,13 +1342,28 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {...@@ -1342,13 +1342,28 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
1342}1342}
13431343
1344// TODO: Implement1344// TODO: Implement
1345static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs);1345static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
1346
1347}
13461348
1347// TODO: Implement1349// TODO: Implement
1348static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs);1350zig_extern zig_u128 __udivmodti4(zig_u128 lhs, zig_u128 rhs, zig_u128* rem);
1351static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
1352 zig_u128 rem;
1353 return __udivmodti4(lhs, rhs, &rem);
1354};
13491355
1350// TODO: Implement1356// TODO: Implement
1351static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs);1357zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
1358static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
1359 return __modti3(lhs, rhs);
1360}
1361
1362// TODO: Implement
1363zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
1364static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
1365 return __umodti3(lhs, rhs);
1366}
13521367
1353static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {1368static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
1354 zig_i128 rem = zig_rem_i128(lhs, rhs);1369 zig_i128 rem = zig_rem_i128(lhs, rhs);
...@@ -1413,8 +1428,16 @@ static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {...@@ -1413,8 +1428,16 @@ static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) {
1413 return zig_wrap_i128(zig_bitcast_i128(zig_sub_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);1428 return zig_wrap_i128(zig_bitcast_i128(zig_sub_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits);
1414}1429}
14151430
1416// TODO: Implement1431#if _MSC_VER
1417static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs);1432static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
1433 zig_u64 lo_carry;
1434 zig_u64 lo = _umul128(lhs.lo, rhs.lo, &lo_carry);
1435 zig_u64 hi = lhs.hi * rhs.lo + lhs.lo * rhs.hi + lo_carry;
1436 return zig_as_u128(hi, lo);
1437}
1438#else
1439static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs); // TODO
1440#endif
14181441
1419static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {1442static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) {
1420 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);1443 return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
...@@ -1636,14 +1659,22 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {...@@ -1636,14 +1659,22 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, zig_u8 bits) {
1636/* ========================= Floating Point Support ========================= */1659/* ========================= Floating Point Support ========================= */
16371660
1638#if _MSC_VER1661#if _MSC_VER
1662#define zig_msvc_flt_inf ((double)(1e+300 * 1e+300))
1663#define zig_msvc_flt_inff ((float)(1e+300 * 1e+300))
1664#define zig_msvc_flt_infl ((long double)(1e+300 * 1e+300))
1665#define zig_msvc_flt_nan ((double)(zig_msvc_flt_inf * 0.f))
1666#define zig_msvc_flt_nanf ((float)(zig_msvc_flt_inf * 0.f))
1667#define zig_msvc_flt_nanl ((long double)(zig_msvc_flt_inf * 0.f))
1639#define __builtin_nan(str) nan(str)1668#define __builtin_nan(str) nan(str)
1640#define __builtin_nanf(str) nanf(str)1669#define __builtin_nanf(str) nanf(str)
1641#define __builtin_nanl(str) nanl(str)1670#define __builtin_nanl(str) nanl(str)
1671#define __builtin_inf() zig_msvc_flt_inf
1642#endif1672#endif
16431673
1644#define zig_has_f16 11674#define zig_has_f16 1
1645#define zig_bitSizeOf_f16 161675#define zig_bitSizeOf_f16 16
1646#define zig_libc_name_f16(name) __##name##h1676#define zig_libc_name_f16(name) __##name##h
1677#define zig_as_special_constant_f16(sign, name, arg, repr) zig_as_special_f16(sign, name, arg, repr)
1647#define zig_as_special_f16(sign, name, arg, repr) sign zig_as_f16(__builtin_##name, )(arg)1678#define zig_as_special_f16(sign, name, arg, repr) sign zig_as_f16(__builtin_##name, )(arg)
1648#if FLT_MANT_DIG == 111679#if FLT_MANT_DIG == 11
1649typedef float zig_f16;1680typedef float zig_f16;
...@@ -1669,11 +1700,18 @@ typedef zig_i16 zig_f16;...@@ -1669,11 +1700,18 @@ typedef zig_i16 zig_f16;
1669#define zig_as_f16(fp, repr) repr1700#define zig_as_f16(fp, repr) repr
1670#undef zig_as_special_f161701#undef zig_as_special_f16
1671#define zig_as_special_f16(sign, name, arg, repr) repr1702#define zig_as_special_f16(sign, name, arg, repr) repr
1703#undef zig_as_special_constant_f16
1704#define zig_as_special_constant_f16(sign, name, arg, repr) repr
1672#endif1705#endif
16731706
1674#define zig_has_f32 11707#define zig_has_f32 1
1675#define zig_bitSizeOf_f32 321708#define zig_bitSizeOf_f32 32
1676#define zig_libc_name_f32(name) name##f1709#define zig_libc_name_f32(name) name##f
1710#if _MSC_VER
1711#define zig_as_special_constant_f32(sign, name, arg, repr) sign zig_as_f32(zig_msvc_flt_##name, )
1712#else
1713#define zig_as_special_constant_f32(sign, name, arg, repr) zig_as_special_f32(sign, name, arg, repr)
1714#endif
1677#define zig_as_special_f32(sign, name, arg, repr) sign zig_as_f32(__builtin_##name, )(arg)1715#define zig_as_special_f32(sign, name, arg, repr) sign zig_as_f32(__builtin_##name, )(arg)
1678#if FLT_MANT_DIG == 241716#if FLT_MANT_DIG == 24
1679typedef float zig_f32;1717typedef float zig_f32;
...@@ -1696,11 +1734,18 @@ typedef zig_i32 zig_f32;...@@ -1696,11 +1734,18 @@ typedef zig_i32 zig_f32;
1696#define zig_as_f32(fp, repr) repr1734#define zig_as_f32(fp, repr) repr
1697#undef zig_as_special_f321735#undef zig_as_special_f32
1698#define zig_as_special_f32(sign, name, arg, repr) repr1736#define zig_as_special_f32(sign, name, arg, repr) repr
1737#undef zig_as_special_constant_f32
1738#define zig_as_special_constant_f32(sign, name, arg, repr) repr
1699#endif1739#endif
17001740
1701#define zig_has_f64 11741#define zig_has_f64 1
1702#define zig_bitSizeOf_f64 641742#define zig_bitSizeOf_f64 64
1703#define zig_libc_name_f64(name) name1743#define zig_libc_name_f64(name) name
1744#if _MSC_VER
1745#define zig_as_special_constant_f64(sign, name, arg, repr) sign zig_as_f64(zig_msvc_flt_##name, )
1746#else
1747#define zig_as_special_constant_f64(sign, name, arg, repr) zig_as_special_f64(sign, name, arg, repr)
1748#endif
1704#define zig_as_special_f64(sign, name, arg, repr) sign zig_as_f64(__builtin_##name, )(arg)1749#define zig_as_special_f64(sign, name, arg, repr) sign zig_as_f64(__builtin_##name, )(arg)
1705#if FLT_MANT_DIG == 531750#if FLT_MANT_DIG == 53
1706typedef float zig_f64;1751typedef float zig_f64;
...@@ -1726,11 +1771,14 @@ typedef zig_i64 zig_f64;...@@ -1726,11 +1771,14 @@ typedef zig_i64 zig_f64;
1726#define zig_as_f64(fp, repr) repr1771#define zig_as_f64(fp, repr) repr
1727#undef zig_as_special_f641772#undef zig_as_special_f64
1728#define zig_as_special_f64(sign, name, arg, repr) repr1773#define zig_as_special_f64(sign, name, arg, repr) repr
1774#undef zig_as_special_constant_f64
1775#define zig_as_special_constant_f64(sign, name, arg, repr) repr
1729#endif1776#endif
17301777
1731#define zig_has_f80 11778#define zig_has_f80 1
1732#define zig_bitSizeOf_f80 801779#define zig_bitSizeOf_f80 80
1733#define zig_libc_name_f80(name) __##name##x1780#define zig_libc_name_f80(name) __##name##x
1781#define zig_as_special_constant_f80(sign, name, arg, repr) zig_as_special_f80(sign, name, arg, repr)
1734#define zig_as_special_f80(sign, name, arg, repr) sign zig_as_f80(__builtin_##name, )(arg)1782#define zig_as_special_f80(sign, name, arg, repr) sign zig_as_f80(__builtin_##name, )(arg)
1735#if FLT_MANT_DIG == 641783#if FLT_MANT_DIG == 64
1736typedef float zig_f80;1784typedef float zig_f80;
...@@ -1759,11 +1807,14 @@ typedef zig_i128 zig_f80;...@@ -1759,11 +1807,14 @@ typedef zig_i128 zig_f80;
1759#define zig_as_f80(fp, repr) repr1807#define zig_as_f80(fp, repr) repr
1760#undef zig_as_special_f801808#undef zig_as_special_f80
1761#define zig_as_special_f80(sign, name, arg, repr) repr1809#define zig_as_special_f80(sign, name, arg, repr) repr
1810#undef zig_as_special_constant_f80
1811#define zig_as_special_constant_f80(sign, name, arg, repr) repr
1762#endif1812#endif
17631813
1764#define zig_has_f128 11814#define zig_has_f128 1
1765#define zig_bitSizeOf_f128 1281815#define zig_bitSizeOf_f128 128
1766#define zig_libc_name_f128(name) name##q1816#define zig_libc_name_f128(name) name##q
1817#define zig_as_special_constant_f128(sign, name, arg, repr) zig_as_special_f128(sign, name, arg, repr)
1767#define zig_as_special_f128(sign, name, arg, repr) sign zig_as_f128(__builtin_##name, )(arg)1818#define zig_as_special_f128(sign, name, arg, repr) sign zig_as_f128(__builtin_##name, )(arg)
1768#if FLT_MANT_DIG == 1131819#if FLT_MANT_DIG == 113
1769typedef float zig_f128;1820typedef float zig_f128;
...@@ -1794,10 +1845,13 @@ typedef zig_i128 zig_f128;...@@ -1794,10 +1845,13 @@ typedef zig_i128 zig_f128;
1794#define zig_as_f128(fp, repr) repr1845#define zig_as_f128(fp, repr) repr
1795#undef zig_as_special_f1281846#undef zig_as_special_f128
1796#define zig_as_special_f128(sign, name, arg, repr) repr1847#define zig_as_special_f128(sign, name, arg, repr) repr
1848#undef zig_as_special_constant_f128
1849#define zig_as_special_constant_f128(sign, name, arg, repr) repr
1797#endif1850#endif
17981851
1799#define zig_has_c_longdouble 11852#define zig_has_c_longdouble 1
1800#define zig_libc_name_c_longdouble(name) name##l1853#define zig_libc_name_c_longdouble(name) name##l
1854#define zig_as_special_constant_c_longdouble(sign, name, arg, repr) zig_as_special_c_longdouble(sign, name, arg, repr)
1801#define zig_as_special_c_longdouble(sign, name, arg, repr) sign __builtin_##name##l(arg)1855#define zig_as_special_c_longdouble(sign, name, arg, repr) sign __builtin_##name##l(arg)
1802#if !_MSC_VER // TODO: Is there a better way to detect this is just double?1856#if !_MSC_VER // TODO: Is there a better way to detect this is just double?
1803typedef long double zig_c_longdouble;1857typedef long double zig_c_longdouble;
...@@ -1811,6 +1865,8 @@ typedef zig_i128 zig_c_longdouble;...@@ -1811,6 +1865,8 @@ typedef zig_i128 zig_c_longdouble;
1811#define zig_as_c_longdouble(fp, repr) repr1865#define zig_as_c_longdouble(fp, repr) repr
1812#undef zig_as_special_c_longdouble1866#undef zig_as_special_c_longdouble
1813#define zig_as_special_c_longdouble(sign, name, arg, repr) repr1867#define zig_as_special_c_longdouble(sign, name, arg, repr) repr
1868#undef zig_as_special_constant_c_longdouble
1869#define zig_as_special_constant_c_longdouble(sign, name, arg, repr) repr
1814#endif1870#endif
18151871
1816#define zig_cast_f16 (zig_f16)1872#define zig_cast_f16 (zig_f16)
src/codegen/c.zig+42-29
...@@ -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 };
714718
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 }
786790
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;
805809
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);
808812
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 }
847851
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 nan965 // 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 else972 else
969 unreachable;973 unreachable;
970974
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;
10231038
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 literal1100 // 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;
10871102
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;
11631179
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;
11981214
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;
12651281
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 });
12711284
1272 empty = false;1285 empty = false;
1273 }1286 }
...@@ -1297,7 +1310,7 @@ pub const DeclGen = struct {...@@ -1297,7 +1310,7 @@ pub const DeclGen = struct {
12971310
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 initializers7254 // 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 }