diff --git a/ci/x86_64-windows-debug.ps1 b/ci/x86_64-windows-debug.ps1 index b7cde7d4f9..52d95f2959 100644 --- a/ci/x86_64-windows-debug.ps1 +++ b/ci/x86_64-windows-debug.ps1 @@ -67,14 +67,16 @@ Write-Output "Testing Autodocs..." -fno-emit-bin CheckLastExitCode -Write-Output "Build behavior tests using the C backend..." +Write-Output "Build x86_64-windows-msvc behavior tests using the C backend..." & "stage3-debug\bin\zig.exe" test ` ..\test\behavior.zig ` --zig-lib-dir "$ZIG_LIB_DIR" ` -I..\test ` -I..\lib ` -ofmt=c ` - -femit-bin="test_behavior.c" + -femit-bin="test-x86_64-windows-msvc.c" ` + --test-no-exec ` + -target x86_64-windows-msvc CheckLastExitCode & "stage3-debug\bin\zig.exe" build-obj ` @@ -83,8 +85,9 @@ CheckLastExitCode -ofmt=c ` -OReleaseSmall ` --name compiler_rt ` - -femit-bin="compiler_rt.c" ` - --pkg-begin build_options config.zig --pkg-end + -femit-bin="compiler_rt-x86_64-windows-msvc.c" ` + --pkg-begin build_options config.zig --pkg-end ` + -target x86_64-windows-msvc CheckLastExitCode Import-Module "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" @@ -96,8 +99,8 @@ Enter-VsDevShell -VsInstallPath "C:\Program Files\Microsoft Visual Studio\2022\E CheckLastExitCode Write-Output "Build and run behavior tests with msvc..." -& cl.exe -I..\lib test_behavior.c compiler_rt.c /W3 /Z7 -link -nologo -debug -subsystem:console -entry:wWinMainCRTStartup kernel32.lib ntdll.lib vcruntime.lib libucrt.lib +& cl.exe -I..\lib test-x86_64-windows-msvc.c compiler_rt-x86_64-windows-msvc.c /W3 /Z7 -link -nologo -debug -subsystem:console -entry:wWinMainCRTStartup kernel32.lib ntdll.lib vcruntime.lib libucrt.lib CheckLastExitCode -& .\test_behavior.exe +& .\test-x86_64-windows-msvc.exe CheckLastExitCode diff --git a/ci/x86_64-windows-release.ps1 b/ci/x86_64-windows-release.ps1 index f2b3d84a26..6ab689ad7c 100644 --- a/ci/x86_64-windows-release.ps1 +++ b/ci/x86_64-windows-release.ps1 @@ -67,14 +67,16 @@ Write-Output "Testing Autodocs..." -fno-emit-bin CheckLastExitCode -Write-Output "Build behavior tests using the C backend..." +Write-Output "Build x86_64-windows-msvc behavior tests using the C backend..." & "stage3-release\bin\zig.exe" test ` ..\test\behavior.zig ` --zig-lib-dir "$ZIG_LIB_DIR" ` -I..\test ` -I..\lib ` -ofmt=c ` - -femit-bin="test_behavior.c" + -femit-bin="test-x86_64-windows-msvc.c" ` + --test-no-exec ` + -target x86_64-windows-msvc CheckLastExitCode & "stage3-release\bin\zig.exe" build-obj ` @@ -83,8 +85,9 @@ CheckLastExitCode -ofmt=c ` -OReleaseSmall ` --name compiler_rt ` - -femit-bin="compiler_rt.c" ` - --pkg-begin build_options config.zig --pkg-end + -femit-bin="compiler_rt-x86_64-windows-msvc.c" ` + --pkg-begin build_options config.zig --pkg-end ` + -target x86_64-windows-msvc CheckLastExitCode Import-Module "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" @@ -96,8 +99,8 @@ Enter-VsDevShell -VsInstallPath "C:\Program Files\Microsoft Visual Studio\2022\E CheckLastExitCode Write-Output "Build and run behavior tests with msvc..." -& cl.exe -I..\lib test_behavior.c compiler_rt.c /W3 /Z7 -link -nologo -debug -subsystem:console -entry:wWinMainCRTStartup kernel32.lib ntdll.lib vcruntime.lib libucrt.lib +& cl.exe -I..\lib test-x86_64-windows-msvc.c compiler_rt-x86_64-windows-msvc.c /W3 /Z7 -link -nologo -debug -subsystem:console -entry:wWinMainCRTStartup kernel32.lib ntdll.lib vcruntime.lib libucrt.lib CheckLastExitCode -& .\test_behavior.exe +& .\test-x86_64-windows-msvc.exe CheckLastExitCode diff --git a/lib/compiler_rt/aulldiv.zig b/lib/compiler_rt/aulldiv.zig index 6c7d90f948..95e1f2eaa2 100644 --- a/lib/compiler_rt/aulldiv.zig +++ b/lib/compiler_rt/aulldiv.zig @@ -7,7 +7,7 @@ const common = @import("common.zig"); pub const panic = common.panic; comptime { - if (arch == .x86 and abi == .msvc) { + if (arch == .x86 and abi == .msvc and builtin.zig_backend != .stage2_c) { // Don't let LLVM apply the stdcall name mangling on those MSVC builtins @export(_alldiv, .{ .name = "\x01__alldiv", .linkage = common.linkage, .visibility = common.visibility }); @export(_aulldiv, .{ .name = "\x01__aulldiv", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/aullrem.zig b/lib/compiler_rt/aullrem.zig index 63a35e518f..2bbcf6626c 100644 --- a/lib/compiler_rt/aullrem.zig +++ b/lib/compiler_rt/aullrem.zig @@ -7,7 +7,7 @@ const common = @import("common.zig"); pub const panic = common.panic; comptime { - if (arch == .x86 and abi == .msvc) { + if (arch == .x86 and abi == .msvc and builtin.zig_backend != .stage2_c) { // Don't let LLVM apply the stdcall name mangling on those MSVC builtins @export(_allrem, .{ .name = "\x01__allrem", .linkage = common.linkage, .visibility = common.visibility }); @export(_aullrem, .{ .name = "\x01__aullrem", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 394936e709..e53387b27c 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -1804,14 +1804,21 @@ pub fn UnlockFile( /// This is a workaround for the C backend until zig has the ability to put /// C code in inline assembly. +extern fn zig_x86_windows_teb() callconv(.C) *anyopaque; extern fn zig_x86_64_windows_teb() callconv(.C) *anyopaque; pub fn teb() *TEB { return switch (native_arch) { - .x86 => asm volatile ( - \\ movl %%fs:0x18, %[ptr] - : [ptr] "=r" (-> *TEB), - ), + .x86 => blk: { + if (builtin.zig_backend == .stage2_c) { + break :blk @ptrCast(*TEB, @alignCast(@alignOf(TEB), zig_x86_windows_teb())); + } else { + break :blk asm volatile ( + \\ movl %%fs:0x18, %[ptr] + : [ptr] "=r" (-> *TEB), + ); + } + }, .x86_64 => blk: { if (builtin.zig_backend == .stage2_c) { break :blk @ptrCast(*TEB, @alignCast(@alignOf(TEB), zig_x86_64_windows_teb())); diff --git a/lib/std/start_windows_tls.zig b/lib/std/start_windows_tls.zig index b8d5ebc954..0a81f13d46 100644 --- a/lib/std/start_windows_tls.zig +++ b/lib/std/start_windows_tls.zig @@ -7,14 +7,12 @@ export var _tls_end: u8 linksection(".tls$ZZZ") = 0; export var __xl_a: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null; export var __xl_z: std.os.windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null; +const tls_array: u32 = 0x2c; comptime { if (builtin.target.cpu.arch == .x86) { // The __tls_array is the offset of the ThreadLocalStoragePointer field // in the TEB block whose base address held in the %fs segment. - asm ( - \\ .global __tls_array - \\ __tls_array = 0x2C - ); + @export(tls_array, .{ .name = "_tls_array" }); } } diff --git a/lib/std/target.zig b/lib/std/target.zig index fa4623d248..4964e75852 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1821,7 +1821,7 @@ pub const Target = struct { .wasm64, => 8, - .x86 => return switch (target.os.tag) { + .x86 => if (target.ofmt == .c) 16 else return switch (target.os.tag) { .windows, .uefi => 8, else => 4, }, diff --git a/lib/zig.h b/lib/zig.h index c2c900ba8c..fb9698325e 100644 --- a/lib/zig.h +++ b/lib/zig.h @@ -52,15 +52,20 @@ typedef char bool; #if _MSC_VER #define zig_const_arr +#define zig_callconv(c) __##c #else #define zig_const_arr static const +#define zig_callconv(c) __attribute__((c)) #endif #if zig_has_attribute(naked) || defined(zig_gnuc) +#define zig_naked_decl __attribute__((naked)) #define zig_naked __attribute__((naked)) #elif defined(_MSC_VER) +#define zig_naked_decl #define zig_naked __declspec(naked) #else +#define zig_naked_decl zig_naked_unavailable #define zig_naked zig_naked_unavailable #endif @@ -111,8 +116,13 @@ typedef char bool; #if zig_has_attribute(alias) #define zig_export(sig, symbol, name) zig_extern sig __attribute__((alias(symbol))) #elif _MSC_VER +#if _M_X64 #define zig_export(sig, symbol, name) sig;\ __pragma(comment(linker, "/alternatename:" name "=" symbol )) +#else /*_M_X64 */ +#define zig_export(sig, symbol, name) sig;\ + __pragma(comment(linker, "/alternatename:_" name "=_" symbol )) +#endif /*_M_X64 */ #else #define zig_export(sig, symbol, name) __asm(name " = " symbol) #endif @@ -220,7 +230,12 @@ typedef char bool; #define zig_atomicrmw_max(obj, arg, order, type) zig_expand_concat(zig_msvc_atomicrmw_max_, type)(obj, arg) #define zig_atomic_store(obj, arg, order, type) zig_expand_concat(zig_msvc_atomic_store_, type)(obj, arg) #define zig_atomic_load(obj, order, type) zig_expand_concat(zig_msvc_atomic_load_, type)(obj) +#if _M_X64 #define zig_fence(order) __faststorefence() +#else +#define zig_fence(order) zig_msvc_atomic_barrier() +#endif + // TODO: _MSC_VER && (_M_ARM || _M_ARM64) #else #define memory_order_relaxed 0 @@ -1214,8 +1229,14 @@ typedef struct { zig_align(16) zig_i64 hi; zig_u64 lo; } zig_i128; #define zig_as_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) }) #define zig_as_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) }) + +#if _MSC_VER #define zig_as_constant_u128(hi, lo) { .h##i = (hi), .l##o = (lo) } #define zig_as_constant_i128(hi, lo) { .h##i = (hi), .l##o = (lo) } +#else +#define zig_as_constant_u128(hi, lo) zig_as_u128(hi, lo) +#define zig_as_constant_i128(hi, lo) zig_as_i128(hi, lo) +#endif #define zig_hi_u128(val) ((val).hi) #define zig_lo_u128(val) ((val).lo) #define zig_hi_i128(val) ((val).hi) @@ -1344,13 +1365,13 @@ static inline zig_u128 zig_shr_u128(zig_u128 lhs, zig_u8 rhs) { static inline zig_u128 zig_shl_u128(zig_u128 lhs, zig_u8 rhs) { if (rhs == zig_as_u8(0)) return lhs; - if (rhs >= zig_as_u8(64)) return (zig_u128){ .hi = lhs.lo << rhs, .lo = zig_minInt_u64 }; + if (rhs >= zig_as_u8(64)) return (zig_u128){ .hi = lhs.lo << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 }; return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs }; } static inline zig_i128 zig_shl_i128(zig_i128 lhs, zig_u8 rhs) { if (rhs == zig_as_u8(0)) return lhs; - if (rhs >= zig_as_u8(64)) return (zig_i128){ .hi = lhs.lo << rhs, .lo = zig_minInt_u64 }; + if (rhs >= zig_as_u8(64)) return (zig_i128){ .hi = lhs.lo << (rhs - zig_as_u8(64)), .lo = zig_minInt_u64 }; return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (zig_as_u8(64) - rhs), .lo = lhs.lo << rhs }; } @@ -1379,6 +1400,10 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) { } zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); +static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) { + return zig_bitcast_u128(__multi3(zig_bitcast_i128(lhs), zig_bitcast_i128(rhs))); +} + static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { return __multi3(lhs, rhs); } @@ -1474,17 +1499,6 @@ static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, zig_u8 bits) { return zig_wrap_i128(zig_bitcast_i128(zig_sub_u128(zig_bitcast_u128(lhs), zig_bitcast_u128(rhs))), bits); } -#if _MSC_VER -static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) { - zig_u64 lo_carry; - zig_u64 lo = _umul128(lhs.lo, rhs.lo, &lo_carry); - zig_u64 hi = lhs.hi * rhs.lo + lhs.lo * rhs.hi + lo_carry; - return zig_as_u128(hi, lo); -} -#else -static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs); // TODO -#endif - static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, zig_u8 bits) { return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits); } @@ -1857,10 +1871,13 @@ typedef zig_i32 zig_f32; #define zig_bitSizeOf_f64 64 #define zig_libc_name_f64(name) name #if _MSC_VER -#define zig_as_special_constant_f64(sign, name, arg, repr) sign zig_as_f64(zig_msvc_flt_##name, ) -#else -#define zig_as_special_constant_f64(sign, name, arg, repr) zig_as_special_f64(sign, name, arg, repr) +#ifdef ZIG_TARGET_ABI_MSVC +#define zig_bitSizeOf_c_longdouble 64 #endif +#define zig_as_special_constant_f64(sign, name, arg, repr) sign zig_as_f64(zig_msvc_flt_##name, ) +#else /* _MSC_VER */ +#define zig_as_special_constant_f64(sign, name, arg, repr) zig_as_special_f64(sign, name, arg, repr) +#endif /* _MSC_VER */ #if FLT_MANT_DIG == 53 typedef float zig_f64; #define zig_as_f64(fp, repr) fp##f @@ -1962,16 +1979,32 @@ typedef zig_i128 zig_f128; #endif #define zig_has_c_longdouble 1 + +#ifdef ZIG_TARGET_ABI_MSVC +#define zig_libc_name_c_longdouble(name) name +#else #define zig_libc_name_c_longdouble(name) name##l +#endif + #define zig_as_special_constant_c_longdouble(sign, name, arg, repr) zig_as_special_c_longdouble(sign, name, arg, repr) #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 +#define zig_as_c_longdouble(fp, repr) fp +#else typedef long double zig_c_longdouble; #define zig_as_c_longdouble(fp, repr) fp##l -#else +#endif + +#else /* zig_bitSizeOf_c_longdouble */ + #undef zig_has_c_longdouble +#define zig_has_c_longdouble 0 #define zig_bitSizeOf_c_longdouble 80 #define zig_compiler_rt_abbrev_c_longdouble zig_compiler_rt_abbrev_f80 -#define zig_has_c_longdouble 0 #define zig_repr_c_longdouble i128 typedef zig_i128 zig_c_longdouble; #define zig_as_c_longdouble(fp, repr) repr @@ -1979,19 +2012,26 @@ typedef zig_i128 zig_c_longdouble; #define zig_as_special_c_longdouble(sign, name, arg, repr) repr #undef zig_as_special_constant_c_longdouble #define zig_as_special_constant_c_longdouble(sign, name, arg, repr) repr -#endif + +#endif /* zig_bitSizeOf_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); \ } + 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 #endif #define zig_cast_f16 (zig_f16) @@ -2218,8 +2258,11 @@ zig_msvc_atomics(u16, 16) zig_msvc_atomics(i16, 16) zig_msvc_atomics(u32, ) zig_msvc_atomics(i32, ) + +#if _M_X64 zig_msvc_atomics(u64, 64) zig_msvc_atomics(i64, 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) { \ @@ -2259,9 +2302,18 @@ zig_msvc_atomics(i64, 64) } zig_msvc_flt_atomics(f32, u32, ) +#if _M_X64 zig_msvc_flt_atomics(f64, u64, 64) +#endif #if _M_IX86 +static inline void zig_msvc_atomic_barrier() { + zig_i32 barrier; + __asm { + xchg barrier, eax + } +} + static inline void* zig_msvc_atomicrmw_xchg_p32(void** obj, zig_u32* arg) { return _InterlockedExchangePointer(obj, arg); } @@ -2270,7 +2322,7 @@ static inline void zig_msvc_atomic_store_p32(void** obj, zig_u32* arg) { _InterlockedExchangePointer(obj, arg); } -static inline void* zig_msvc_atomic_load_p32(void** obj, zig_u32* arg) { +static inline void* zig_msvc_atomic_load_p32(void** obj) { return (void*)_InterlockedOr((void*)obj, 0); } @@ -2283,7 +2335,7 @@ static inline bool zig_msvc_cmpxchg_p32(void** obj, void** expected, void* desir } return exchanged; } -#else +#else /* _M_IX86 */ static inline void* zig_msvc_atomicrmw_xchg_p64(void** obj, zig_u64* arg) { return _InterlockedExchangePointer(obj, arg); } @@ -2305,7 +2357,6 @@ static inline bool zig_msvc_cmpxchg_p64(void** obj, void** expected, void* desir } return exchanged; } -#endif static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128* expected, zig_u128 desired) { return _InterlockedCompareExchange128((zig_i64 volatile*)obj, desired.hi, desired.lo, (zig_i64*)expected); @@ -2350,6 +2401,7 @@ zig_msvc_atomics_128op(u128, and) zig_msvc_atomics_128op(u128, nand) zig_msvc_atomics_128op(u128, min) zig_msvc_atomics_128op(u128, max) +#endif /* _M_IX86 */ #endif /* _MSC_VER && (_M_IX86 || _M_X64) */ @@ -2359,7 +2411,7 @@ zig_msvc_atomics_128op(u128, max) static inline void* zig_x86_64_windows_teb(void) { #if _MSC_VER - return __readgsqword(0x30); + return (void*)__readgsqword(0x30); #else void* teb; __asm volatile(" movq %%gs:0x30, %[ptr]": [ptr]"=r"(teb)::); @@ -2367,6 +2419,18 @@ static inline void* zig_x86_64_windows_teb(void) { #endif } +#elif (_MSC_VER && _M_IX86) || defined(__i386__) || defined(__X86__) + +static inline void* zig_x86_windows_teb(void) { +#if _MSC_VER + return (void*)__readfsdword(0x18); +#else + void* teb; + __asm volatile(" movl %%fs:0x18, %[ptr]": [ptr]"=r"(teb)::); + return teb; +#endif +} + #endif #if (_MSC_VER && (_M_IX86 || _M_X64)) || defined(__i386__) || defined(__x86_64__) diff --git a/src/codegen/c.zig b/src/codegen/c.zig index c1adbfe6cf..68c20ea49c 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1459,7 +1459,12 @@ pub const DeclGen = struct { fn renderFunctionSignature(dg: *DeclGen, w: anytype, kind: TypedefKind, export_index: u32) !void { const fn_info = dg.decl.ty.fnInfo(); - if (fn_info.cc == .Naked) try w.writeAll("zig_naked "); + if (fn_info.cc == .Naked) { + switch (kind) { + .Forward => try w.writeAll("zig_naked_decl "), + .Complete => try w.writeAll("zig_naked "), + } + } if (dg.decl.val.castTag(.function)) |func_payload| if (func_payload.data.is_cold) try w.writeAll("zig_cold "); @@ -1469,6 +1474,13 @@ pub const DeclGen = struct { try dg.renderType(w, ret_ty, kind); try w.writeByte(' '); + + if (toCallingConvention(fn_info.cc)) |call_conv| { + try w.print("zig_callconv({s}) ", .{call_conv}); + } + + if (fn_info.alignment > 0 and kind == .Complete) try w.print(" zig_align_fn({})", .{fn_info.alignment}); + try dg.renderDeclName(w, dg.decl_index, export_index); try w.writeByte('('); @@ -1488,7 +1500,7 @@ pub const DeclGen = struct { try dg.renderType(w, Type.void, kind); } try w.writeByte(')'); - if (fn_info.alignment > 0) try w.print(" zig_align_fn({})", .{fn_info.alignment}); + if (fn_info.alignment > 0 and kind == .Forward) try w.print(" zig_align_fn({})", .{fn_info.alignment}); } fn renderPtrToFnTypedef(dg: *DeclGen, t: Type) error{ OutOfMemory, AnalysisFail }![]const u8 { @@ -7035,6 +7047,15 @@ fn writeMemoryOrder(w: anytype, order: std.builtin.AtomicOrder) !void { return w.writeAll(toMemoryOrder(order)); } +fn toCallingConvention(call_conv: std.builtin.CallingConvention) ?[]const u8 { + return switch (call_conv) { + .Stdcall => "stdcall", + .Fastcall => "fastcall", + .Vectorcall => "vectorcall", + else => null, + }; +} + fn toAtomicRmwSuffix(order: std.builtin.AtomicRmwOp) []const u8 { return switch (order) { .Xchg => "xchg", diff --git a/src/link/C.zig b/src/link/C.zig index ad50a20b99..8b05b8b22d 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -231,6 +231,13 @@ pub fn flush(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void return self.flushModule(comp, prog_node); } +fn abiDefine(comp: *Compilation) ?[]const u8 { + return switch (comp.getTarget().abi) { + .msvc => "#define ZIG_TARGET_ABI_MSVC\n", + else => null, + }; +} + pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) !void { const tracy = trace(@src()); defer tracy.end(); @@ -248,9 +255,14 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node) var f: Flush = .{}; defer f.deinit(gpa); - // Covers zig.h, typedef, and asm. - try f.all_buffers.ensureUnusedCapacity(gpa, 2); + const abi_define = abiDefine(comp); + // Covers defines, zig.h, typedef, and asm. + var buf_count: usize = 2; + if (abi_define != null) buf_count += 1; + try f.all_buffers.ensureUnusedCapacity(gpa, buf_count); + + if (abi_define) |buf| f.appendBufAssumeCapacity(buf); f.appendBufAssumeCapacity(zig_h); const typedef_index = f.all_buffers.items.len; diff --git a/stage1/zig1.wasm b/stage1/zig1.wasm index 88186ff514..4405298016 100644 Binary files a/stage1/zig1.wasm and b/stage1/zig1.wasm differ diff --git a/test/behavior/align.zig b/test/behavior/align.zig index 8272a852df..162c798758 100644 --- a/test/behavior/align.zig +++ b/test/behavior/align.zig @@ -104,7 +104,18 @@ test "alignment and size of structs with 128-bit fields" { .u129_size = 24, }, - .x86 => switch (builtin.os.tag) { + .x86 => if (builtin.object_format == .c) .{ + .a_align = 16, + .a_size = 16, + + .b_align = 16, + .b_size = 32, + + .u128_align = 16, + .u128_size = 16, + .u129_align = 16, + .u129_size = 32, + } else switch (builtin.os.tag) { .windows => .{ .a_align = 8, .a_size = 16, diff --git a/test/behavior/int128.zig b/test/behavior/int128.zig index f02795cebe..85598b3585 100644 --- a/test/behavior/int128.zig +++ b/test/behavior/int128.zig @@ -84,3 +84,31 @@ test "truncate int128" { try expect(@truncate(i128, buff) == maxInt(i128)); } } + +test "shift int128" { + if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO + + const types = .{ u128, i128 }; + inline for (types) |t| { + try testShlTrunc(t, 0x8, 123); + comptime try testShlTrunc(t, 0x8, 123); + + try testShlTrunc(t, 0x40000000_00000000, 64); + comptime try testShlTrunc(t, 0x40000000_00000000, 64); + + try testShlTrunc(t, 0x01000000_00000000_00000000, 38); + comptime try testShlTrunc(t, 0x01000000_00000000_00000000, 38); + + try testShlTrunc(t, 0x00000008_00000000_00000000_00000000, 27); + comptime try testShlTrunc(t, 0x00000008_00000000_00000000_00000000, 27); + } +} + +fn testShlTrunc(comptime Type: type, x: Type, rhs: u7) !void { + const shifted = x << rhs; + try expect(shifted == @as(Type, 0x40000000_00000000_00000000_00000000)); +}