Commit 248fb40dcc

Jacob Young <jacobly0@users.noreply.github.com>
2023-02-21 21:05:41
CBE: fix windows test failures
1 parent 434c6f4
Changed files (4)
lib
src
codegen
test
behavior
lib/zig.h
@@ -316,7 +316,7 @@ zig_extern void *memset (void *, int, size_t);
 
 /* ===================== 8/16/32/64-bit Integer Support ===================== */
 
-#if __STDC_VERSION__ >= 199901L
+#if __STDC_VERSION__ >= 199901L || _MSC_VER
 #include <stdint.h>
 #else
 
@@ -1923,6 +1923,7 @@ typedef double zig_f16;
 #define zig_make_f16(fp, repr) fp
 #elif LDBL_MANT_DIG == 11
 #define zig_bitSizeOf_c_longdouble 16
+typedef uint16_t zig_repr_c_longdouble;
 typedef long double zig_f16;
 #define zig_make_f16(fp, repr) fp##l
 #elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gnuc))
@@ -1959,6 +1960,7 @@ typedef double zig_f32;
 #define zig_make_f32(fp, repr) fp
 #elif LDBL_MANT_DIG == 24
 #define zig_bitSizeOf_c_longdouble 32
+typedef uint32_t zig_repr_c_longdouble;
 typedef long double zig_f32;
 #define zig_make_f32(fp, repr) fp##l
 #elif FLT32_MANT_DIG == 24
@@ -1982,6 +1984,7 @@ typedef int32_t zig_f32;
 #if _MSC_VER
 #ifdef ZIG_TARGET_ABI_MSVC
 #define zig_bitSizeOf_c_longdouble 64
+typedef uint64_t zig_repr_c_longdouble;
 #endif
 #define zig_make_special_constant_f64(sign, name, arg, repr) sign zig_make_f64(zig_msvc_flt_##name, )
 #else /* _MSC_VER */
@@ -1995,6 +1998,7 @@ typedef double zig_f64;
 #define zig_make_f64(fp, repr) fp
 #elif LDBL_MANT_DIG == 53
 #define zig_bitSizeOf_c_longdouble 64
+typedef uint64_t zig_repr_c_longdouble;
 typedef long double zig_f64;
 #define zig_make_f64(fp, repr) fp##l
 #elif FLT64_MANT_DIG == 53
@@ -2027,6 +2031,7 @@ typedef double zig_f80;
 #define zig_make_f80(fp, repr) fp
 #elif LDBL_MANT_DIG == 64
 #define zig_bitSizeOf_c_longdouble 80
+typedef zig_u128 zig_repr_c_longdouble;
 typedef long double zig_f80;
 #define zig_make_f80(fp, repr) fp##l
 #elif FLT80_MANT_DIG == 64
@@ -2062,6 +2067,7 @@ typedef double zig_f128;
 #define zig_make_f128(fp, repr) fp
 #elif LDBL_MANT_DIG == 113
 #define zig_bitSizeOf_c_longdouble 128
+typedef zig_u128 zig_repr_c_longdouble;
 typedef long double zig_f128;
 #define zig_make_f128(fp, repr) fp##l
 #elif FLT128_MANT_DIG == 113
@@ -2099,9 +2105,10 @@ typedef zig_i128 zig_f128;
 #ifdef zig_bitSizeOf_c_longdouble
 
 #ifdef ZIG_TARGET_ABI_MSVC
-typedef double zig_c_longdouble;
 #undef zig_bitSizeOf_c_longdouble
 #define zig_bitSizeOf_c_longdouble 64
+typedef uint64_t zig_repr_c_longdouble;
+typedef zig_f64 zig_c_longdouble;
 #define zig_make_c_longdouble(fp, repr) fp
 #else
 typedef long double zig_c_longdouble;
@@ -2113,6 +2120,7 @@ typedef long double zig_c_longdouble;
 #undef zig_has_c_longdouble
 #define zig_has_c_longdouble 0
 #define zig_bitSizeOf_c_longdouble 80
+typedef zig_u128 zig_repr_c_longdouble;
 #define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f80
 #define zig_bitSizeOf_repr_c_longdouble 128
 typedef zig_i128 zig_c_longdouble;
@@ -2126,21 +2134,18 @@ typedef zig_i128 zig_c_longdouble;
 
 #if !zig_has_float_builtins
 #define zig_float_from_repr(Type, ReprType) \
-    static inline zig_##Type zig_float_from_repr_##Type(zig_##ReprType repr) { \
-        return *((zig_##Type*)&repr); \
+    static inline zig_##Type zig_float_from_repr_##Type(ReprType repr) { \
+        zig_##Type result; \
+        memcpy(&result, &repr, sizeof(result)); \
+        return result; \
     }
 
-zig_float_from_repr(f16, u16)
-zig_float_from_repr(f32, u32)
-zig_float_from_repr(f64, u64)
-zig_float_from_repr(f80, u128)
-zig_float_from_repr(f128, u128)
-#if zig_bitSizeOf_c_longdouble == 80
-zig_float_from_repr(c_longdouble, u128)
-#else
-#define zig_expand_float_from_repr(Type, ReprType) zig_float_from_repr(Type, ReprType)
-zig_expand_float_from_repr(c_longdouble, zig_expand_concat(u, zig_bitSizeOf_c_longdouble))
-#endif
+zig_float_from_repr(f16, uint16_t)
+zig_float_from_repr(f32, uint32_t)
+zig_float_from_repr(f64, uint64_t)
+zig_float_from_repr(f80, zig_u128)
+zig_float_from_repr(f128, zig_u128)
+zig_float_from_repr(c_longdouble, zig_repr_c_longdouble)
 #endif
 
 #define zig_cast_f16 (zig_f16)
@@ -2288,98 +2293,98 @@ zig_float_builtins(c_longdouble)
 
 // TODO: zig_msvc_atomic_load should load 32 bit without interlocked on x86, and load 64 bit without interlocked on x64
 
-#define zig_msvc_atomics(Type, suffix) \
-    static inline bool zig_msvc_cmpxchg_##Type(zig_##Type volatile* obj, zig_##Type* expected, zig_##Type desired) { \
-        zig_##Type comparand = *expected; \
-        zig_##Type initial = _InterlockedCompareExchange##suffix(obj, desired, comparand); \
+#define zig_msvc_atomics(ZigType, Type, suffix) \
+    static inline bool zig_msvc_cmpxchg_##ZigType(Type volatile* obj, Type* expected, Type desired) { \
+        Type comparand = *expected; \
+        Type initial = _InterlockedCompareExchange##suffix(obj, desired, comparand); \
         bool exchanged = initial == comparand; \
         if (!exchanged) { \
             *expected = initial; \
         } \
         return exchanged; \
     } \
-    static inline zig_##Type zig_msvc_atomicrmw_xchg_##Type(zig_##Type volatile* obj, zig_##Type value) { \
+    static inline Type zig_msvc_atomicrmw_xchg_##ZigType(Type volatile* obj, Type value) { \
         return _InterlockedExchange##suffix(obj, value); \
     } \
-    static inline zig_##Type zig_msvc_atomicrmw_add_##Type(zig_##Type volatile* obj, zig_##Type value) { \
+    static inline Type zig_msvc_atomicrmw_add_##ZigType(Type volatile* obj, Type value) { \
         return _InterlockedExchangeAdd##suffix(obj, value); \
     } \
-    static inline zig_##Type zig_msvc_atomicrmw_sub_##Type(zig_##Type volatile* obj, zig_##Type value) { \
+    static inline Type zig_msvc_atomicrmw_sub_##ZigType(Type volatile* obj, Type value) { \
         bool success = false; \
-        zig_##Type new; \
-        zig_##Type prev; \
+        Type new; \
+        Type prev; \
         while (!success) { \
             prev = *obj; \
             new = prev - value; \
-            success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
+            success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
         } \
         return prev; \
     } \
-    static inline zig_##Type zig_msvc_atomicrmw_or_##Type(zig_##Type volatile* obj, zig_##Type value) { \
+    static inline Type zig_msvc_atomicrmw_or_##ZigType(Type volatile* obj, Type value) { \
         return _InterlockedOr##suffix(obj, value); \
     } \
-    static inline zig_##Type zig_msvc_atomicrmw_xor_##Type(zig_##Type volatile* obj, zig_##Type value) { \
+    static inline Type zig_msvc_atomicrmw_xor_##ZigType(Type volatile* obj, Type value) { \
         return _InterlockedXor##suffix(obj, value); \
     } \
-    static inline zig_##Type zig_msvc_atomicrmw_and_##Type(zig_##Type volatile* obj, zig_##Type value) { \
+    static inline Type zig_msvc_atomicrmw_and_##ZigType(Type volatile* obj, Type value) { \
         return _InterlockedAnd##suffix(obj, value); \
     } \
-    static inline zig_##Type zig_msvc_atomicrmw_nand_##Type(zig_##Type volatile* obj, zig_##Type value) { \
+    static inline Type zig_msvc_atomicrmw_nand_##ZigType(Type volatile* obj, Type value) { \
         bool success = false; \
-        zig_##Type new; \
-        zig_##Type prev; \
+        Type new; \
+        Type prev; \
         while (!success) { \
             prev = *obj; \
             new = ~(prev & value); \
-            success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
+            success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
         } \
         return prev; \
     } \
-    static inline zig_##Type zig_msvc_atomicrmw_min_##Type(zig_##Type volatile* obj, zig_##Type value) { \
+    static inline Type zig_msvc_atomicrmw_min_##ZigType(Type volatile* obj, Type value) { \
         bool success = false; \
-        zig_##Type new; \
-        zig_##Type prev; \
+        Type new; \
+        Type prev; \
         while (!success) { \
             prev = *obj; \
             new = value < prev ? value : prev; \
-            success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
+            success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
         } \
         return prev; \
     } \
-    static inline zig_##Type zig_msvc_atomicrmw_max_##Type(zig_##Type volatile* obj, zig_##Type value) { \
+    static inline Type zig_msvc_atomicrmw_max_##ZigType(Type volatile* obj, Type value) { \
         bool success = false; \
-        zig_##Type new; \
-        zig_##Type prev; \
+        Type new; \
+        Type prev; \
         while (!success) { \
             prev = *obj; \
             new = value > prev ? value : prev; \
-            success = zig_msvc_cmpxchg_##Type(obj, &prev, new); \
+            success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
         } \
         return prev; \
     } \
-    static inline void zig_msvc_atomic_store_##Type(zig_##Type volatile* obj, zig_##Type value) { \
+    static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \
         _InterlockedExchange##suffix(obj, value); \
     } \
-    static inline zig_##Type zig_msvc_atomic_load_##Type(zig_##Type volatile* obj) { \
+    static inline Type zig_msvc_atomic_load_##ZigType(Type volatile* obj) { \
         return _InterlockedOr##suffix(obj, 0); \
     }
 
-zig_msvc_atomics(u8, 8)
-zig_msvc_atomics(i8, 8)
-zig_msvc_atomics(u16, 16)
-zig_msvc_atomics(i16, 16)
-zig_msvc_atomics(u32, )
-zig_msvc_atomics(i32, )
+zig_msvc_atomics( u8,  uint8_t,  8)
+zig_msvc_atomics( i8,   int8_t,  8)
+zig_msvc_atomics(u16, uint16_t, 16)
+zig_msvc_atomics(i16,  int16_t, 16)
+zig_msvc_atomics(u32, uint32_t,   )
+zig_msvc_atomics(i32,  int32_t,   )
 
 #if _M_X64
-zig_msvc_atomics(u64, 64)
-zig_msvc_atomics(i64, 64)
+zig_msvc_atomics(u64, uint64_t, 64)
+zig_msvc_atomics(i64,  int64_t, 64)
 #endif
 
 #define zig_msvc_flt_atomics(Type, ReprType, suffix) \
     static inline bool zig_msvc_cmpxchg_##Type(zig_##Type volatile* obj, zig_##Type* expected, zig_##Type desired) { \
-        zig_##ReprType comparand = *((zig_##ReprType*)expected); \
-        zig_##ReprType initial = _InterlockedCompareExchange##suffix((zig_##ReprType volatile*)obj, *((zig_##ReprType*)&desired), comparand); \
+        ReprType comparand = *((ReprType*)expected); \
+        ReprType initial = _InterlockedCompareExchange##suffix((ReprType volatile*)obj, *((ReprType*)&desired), comparand); \
         bool exchanged = initial == comparand; \
         if (!exchanged) { \
             *expected = *((zig_##Type*)&initial); \
@@ -2387,35 +2392,35 @@ zig_msvc_atomics(i64, 64)
         return exchanged; \
     } \
     static inline zig_##Type zig_msvc_atomicrmw_xchg_##Type(zig_##Type volatile* obj, zig_##Type value) { \
-        zig_##ReprType initial = _InterlockedExchange##suffix((zig_##ReprType volatile*)obj, *((zig_##ReprType*)&value)); \
+        ReprType initial = _InterlockedExchange##suffix((ReprType volatile*)obj, *((ReprType*)&value)); \
         return *((zig_##Type*)&initial); \
     } \
     static inline zig_##Type zig_msvc_atomicrmw_add_##Type(zig_##Type volatile* obj, zig_##Type value) { \
         bool success = false; \
-        zig_##ReprType new; \
+        ReprType new; \
         zig_##Type prev; \
         while (!success) { \
             prev = *obj; \
             new = prev + value; \
-            success = zig_msvc_cmpxchg_##Type(obj, &prev, *((zig_##ReprType*)&new)); \
+            success = zig_msvc_cmpxchg_##Type(obj, &prev, *((ReprType*)&new)); \
         } \
         return prev; \
     } \
     static inline zig_##Type zig_msvc_atomicrmw_sub_##Type(zig_##Type volatile* obj, zig_##Type value) { \
         bool success = false; \
-        zig_##ReprType new; \
+        ReprType new; \
         zig_##Type prev; \
         while (!success) { \
             prev = *obj; \
             new = prev - value; \
-            success = zig_msvc_cmpxchg_##Type(obj, &prev, *((zig_##ReprType*)&new)); \
+            success = zig_msvc_cmpxchg_##Type(obj, &prev, *((ReprType*)&new)); \
         } \
         return prev; \
     }
 
-zig_msvc_flt_atomics(f32, u32, )
+zig_msvc_flt_atomics(f32, uint32_t,   )
 #if _M_X64
-zig_msvc_flt_atomics(f64, u64, 64)
+zig_msvc_flt_atomics(f64, uint64_t, 64)
 #endif
 
 #if _M_IX86
@@ -2426,11 +2431,11 @@ static inline void zig_msvc_atomic_barrier() {
     }
 }
 
-static inline void* zig_msvc_atomicrmw_xchg_p32(void** obj, uint32_t* arg) {
+static inline void* zig_msvc_atomicrmw_xchg_p32(void** obj, void* arg) {
     return _InterlockedExchangePointer(obj, arg);
 }
 
-static inline void zig_msvc_atomic_store_p32(void** obj, uint32_t* arg) {
+static inline void zig_msvc_atomic_store_p32(void** obj, void* arg) {
     _InterlockedExchangePointer(obj, arg);
 }
 
@@ -2448,11 +2453,11 @@ static inline bool zig_msvc_cmpxchg_p32(void** obj, void** expected, void* desir
     return exchanged;
 }
 #else /* _M_IX86 */
-static inline void* zig_msvc_atomicrmw_xchg_p64(void** obj, uint64_t* arg) {
+static inline void* zig_msvc_atomicrmw_xchg_p64(void** obj, void* arg) {
     return _InterlockedExchangePointer(obj, arg);
 }
 
-static inline void zig_msvc_atomic_store_p64(void** obj, uint64_t* arg) {
+static inline void zig_msvc_atomic_store_p64(void** obj, void* arg) {
     _InterlockedExchangePointer(obj, arg);
 }
 
src/codegen/c/type.zig
@@ -102,6 +102,7 @@ pub const CType = extern union {
         zig_f64,
         zig_f80,
         zig_f128,
+        zig_c_longdouble, // Keep last_no_payload_tag updated!
 
         // After this, the tag requires a payload.
         pointer,
@@ -127,7 +128,7 @@ pub const CType = extern union {
         function,
         varargs_function,
 
-        pub const last_no_payload_tag = Tag.zig_f128;
+        pub const last_no_payload_tag = Tag.zig_c_longdouble;
         pub const no_payload_count = @enumToInt(last_no_payload_tag) + 1;
 
         pub fn hasPayload(self: Tag) bool {
@@ -177,6 +178,7 @@ pub const CType = extern union {
                 .zig_f64,
                 .zig_f80,
                 .zig_f128,
+                .zig_c_longdouble,
                 => @compileError("Type Tag " ++ @tagName(self) ++ " has no payload"),
 
                 .pointer,
@@ -557,6 +559,7 @@ pub const CType = extern union {
             .zig_f64,
             .zig_f80,
             .zig_f128,
+            .zig_c_longdouble,
             => false,
 
             .pointer,
@@ -674,6 +677,7 @@ pub const CType = extern union {
             .zig_f64,
             .zig_f80,
             .zig_f128,
+            .zig_c_longdouble,
             => {},
 
             .pointer,
@@ -980,7 +984,7 @@ pub const CType = extern union {
                     .f64 => .zig_f64,
                     .f80 => .zig_f80,
                     .f128 => .zig_f128,
-                    .c_longdouble => .@"long double",
+                    .c_longdouble => .zig_c_longdouble,
                     else => unreachable,
                 }),
 
@@ -1374,6 +1378,7 @@ pub const CType = extern union {
             .zig_f64,
             .zig_f80,
             .zig_f128,
+            .zig_c_longdouble,
             => return self,
 
             .pointer,
src/codegen/c.zig
@@ -2058,6 +2058,7 @@ fn renderTypePrefix(
         .zig_f64,
         .zig_f80,
         .zig_f128,
+        .zig_c_longdouble,
         => |tag| try w.writeAll(@tagName(tag)),
 
         .pointer,
@@ -2225,6 +2226,7 @@ fn renderTypeSuffix(
         .zig_f64,
         .zig_f80,
         .zig_f128,
+        .zig_c_longdouble,
         => {},
 
         .pointer,
@@ -3062,6 +3064,7 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
         return CValue.none;
     }
 
+    const inst_ty = f.air.typeOfIndex(inst);
     const ptr_ty = f.air.typeOf(bin_op.lhs);
     const child_ty = ptr_ty.childType();
 
@@ -3076,7 +3079,9 @@ fn airPtrElemPtr(f: *Function, inst: Air.Inst.Index) !CValue {
     const writer = f.object.writer();
     const local = try f.allocLocal(inst, f.air.typeOfIndex(inst));
     try f.writeCValue(writer, local, .Other);
-    try writer.writeAll(" = &(");
+    try writer.writeAll(" = (");
+    try f.renderTypecast(writer, inst_ty);
+    try writer.writeAll(")&(");
     if (ptr_ty.ptrSize() == .One) {
         // It's a pointer to an array, so we need to de-reference.
         try f.writeCValueDeref(writer, ptr);
@@ -3902,32 +3907,31 @@ fn airPtrAddSub(f: *Function, inst: Air.Inst.Index, operator: u8) !CValue {
     try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
 
     const inst_ty = f.air.typeOfIndex(inst);
-    const elem_ty = switch (inst_ty.ptrSize()) {
-        .One => blk: {
-            const array_ty = inst_ty.childType();
-            break :blk array_ty.childType();
-        },
-        else => inst_ty.childType(),
-    };
+    const elem_ty = inst_ty.elemType2();
 
-    // We must convert to and from integer types to prevent UB if the operation
-    // results in a NULL pointer, or if LHS is NULL. The operation is only UB
-    // if the result is NULL and then dereferenced.
     const local = try f.allocLocal(inst, inst_ty);
     const writer = f.object.writer();
     try f.writeCValue(writer, local, .Other);
-    try writer.writeAll(" = (");
-    try f.renderTypecast(writer, inst_ty);
-    try writer.writeAll(")(((uintptr_t)");
-    try f.writeCValue(writer, lhs, .Other);
-    try writer.writeAll(") ");
-    try writer.writeByte(operator);
-    try writer.writeAll(" (");
-    try f.writeCValue(writer, rhs, .Other);
-    try writer.writeAll("*sizeof(");
-    try f.renderTypecast(writer, elem_ty);
-    try writer.writeAll(")));\n");
+    try writer.writeAll(" = ");
+
+    if (elem_ty.hasRuntimeBitsIgnoreComptime()) {
+        // We must convert to and from integer types to prevent UB if the operation
+        // results in a NULL pointer, or if LHS is NULL. The operation is only UB
+        // if the result is NULL and then dereferenced.
+        try writer.writeByte('(');
+        try f.renderTypecast(writer, inst_ty);
+        try writer.writeAll(")(((uintptr_t)");
+        try f.writeCValue(writer, lhs, .Other);
+        try writer.writeAll(") ");
+        try writer.writeByte(operator);
+        try writer.writeAll(" (");
+        try f.writeCValue(writer, rhs, .Other);
+        try writer.writeAll("*sizeof(");
+        try f.renderTypecast(writer, elem_ty);
+        try writer.writeAll(")))");
+    } else try f.writeCValue(writer, lhs, .Initializer);
 
+    try writer.writeAll(";\n");
     return local;
 }
 
@@ -5264,21 +5268,21 @@ fn structFieldPtr(f: *Function, inst: Air.Inst.Index, struct_ptr_ty: Type, struc
         else => unreachable,
     };
 
-    try writer.writeByte('&');
-    switch (field_loc) {
-        .begin, .end => {
-            try writer.writeByte('(');
-            try f.writeCValue(writer, struct_ptr, .Other);
-            try writer.print(")[{}]", .{
-                @boolToInt(field_loc == .end and struct_ty.hasRuntimeBitsIgnoreComptime()),
-            });
-        },
-        .field => |field| if (extra_name != .none) {
-            try f.writeCValueDerefMember(writer, struct_ptr, extra_name);
-            try writer.writeByte('.');
-            try f.writeCValue(writer, field, .Other);
-        } else try f.writeCValueDerefMember(writer, struct_ptr, field),
-    }
+    if (struct_ty.hasRuntimeBitsIgnoreComptime()) {
+        try writer.writeByte('&');
+        switch (field_loc) {
+            .begin, .end => {
+                try writer.writeByte('(');
+                try f.writeCValue(writer, struct_ptr, .Other);
+                try writer.print(")[{}]", .{@boolToInt(field_loc == .end)});
+            },
+            .field => |field| if (extra_name != .none) {
+                try f.writeCValueDerefMember(writer, struct_ptr, extra_name);
+                try writer.writeByte('.');
+                try f.writeCValue(writer, field, .Other);
+            } else try f.writeCValueDerefMember(writer, struct_ptr, field),
+        }
+    } else try f.writeCValue(writer, struct_ptr, .Other);
     try writer.writeAll(";\n");
     return local;
 }
test/behavior/asm.zig
@@ -7,6 +7,7 @@ const is_x86_64_linux = builtin.cpu.arch == .x86_64 and builtin.os.tag == .linux
 comptime {
     if (builtin.zig_backend != .stage2_arm and
         builtin.zig_backend != .stage2_aarch64 and
+        !(builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) and // MSVC doesn't support inline assembly
         is_x86_64_linux)
     {
         asm (
@@ -24,6 +25,8 @@ test "module level assembly" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 
+    if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
+
     if (is_x86_64_linux) {
         try expect(this_is_my_alias() == 1234);
     }
@@ -36,6 +39,8 @@ test "output constraint modifiers" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 
+    if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
+
     // This is only testing compilation.
     var a: u32 = 3;
     asm volatile (""
@@ -57,6 +62,8 @@ test "alternative constraints" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 
+    if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
+
     // Make sure we allow commas as a separator for alternative constraints.
     var a: u32 = 3;
     asm volatile (""
@@ -73,6 +80,8 @@ test "sized integer/float in asm input" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 
+    if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
+
     asm volatile (""
         :
         : [_] "m" (@as(usize, 3)),
@@ -122,6 +131,8 @@ test "struct/array/union types as input values" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
 
+    if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
+
     asm volatile (""
         :
         : [_] "m" (@as([1]u32, undefined)),
@@ -146,6 +157,8 @@ test "asm modifiers (AArch64)" {
     if (builtin.target.cpu.arch != .aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
 
+    if (builtin.zig_backend == .stage2_c and builtin.os.tag == .windows) return error.SkipZigTest; // MSVC doesn't support inline assembly
+
     var x: u32 = 15;
     const double = asm ("add %[ret:w], %[in:w], %[in:w]"
         : [ret] "=r" (-> u32),