diff --git a/lib/compiler_rt/arm.zig b/lib/compiler_rt/arm.zig index eb78a77470..e42694b2bf 100644 --- a/lib/compiler_rt/arm.zig +++ b/lib/compiler_rt/arm.zig @@ -2,6 +2,7 @@ //! This file includes all ARM-only functions. const std = @import("std"); const builtin = @import("builtin"); +const target = builtin.target; const arch = builtin.cpu.arch; const common = @import("common.zig"); @@ -14,11 +15,11 @@ comptime { @export(&__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = common.linkage, .visibility = common.visibility }); @export(&__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = common.linkage, .visibility = common.visibility }); - @export(&__aeabi_ldivmod, .{ .name = "__aeabi_ldivmod", .linkage = common.linkage, .visibility = common.visibility }); - @export(&__aeabi_uldivmod, .{ .name = "__aeabi_uldivmod", .linkage = common.linkage, .visibility = common.visibility }); + @export(&__aeabi_ldivmod, .{ .name = if (target.isMinGW()) "__rt_sdiv64" else "__aeabi_ldivmod", .linkage = common.linkage, .visibility = common.visibility }); + @export(&__aeabi_uldivmod, .{ .name = if (target.isMinGW()) "__rt_udiv64" else "__aeabi_uldivmod", .linkage = common.linkage, .visibility = common.visibility }); - @export(&__aeabi_idivmod, .{ .name = "__aeabi_idivmod", .linkage = common.linkage, .visibility = common.visibility }); - @export(&__aeabi_uidivmod, .{ .name = "__aeabi_uidivmod", .linkage = common.linkage, .visibility = common.visibility }); + @export(&__aeabi_idivmod, .{ .name = if (target.isMinGW()) "__rt_sdiv" else "__aeabi_idivmod", .linkage = common.linkage, .visibility = common.visibility }); + @export(&__aeabi_uidivmod, .{ .name = if (target.isMinGW()) "__rt_udiv" else "__aeabi_uidivmod", .linkage = common.linkage, .visibility = common.visibility }); @export(&__aeabi_memcpy, .{ .name = "__aeabi_memcpy", .linkage = common.linkage, .visibility = common.visibility }); @export(&__aeabi_memcpy4, .{ .name = "__aeabi_memcpy4", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/lib/compiler_rt/stack_probe.zig b/lib/compiler_rt/stack_probe.zig index 1ca8ad27d1..69de4c8575 100644 --- a/lib/compiler_rt/stack_probe.zig +++ b/lib/compiler_rt/stack_probe.zig @@ -5,9 +5,6 @@ const arch = builtin.cpu.arch; const abi = builtin.abi; const is_test = builtin.is_test; -const is_gnu = abi.isGnu(); -const is_mingw = os_tag == .windows and is_gnu; - const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .internal else .weak; const strong_linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .internal else .strong; pub const panic = @import("common.zig").panic; @@ -15,11 +12,11 @@ pub const panic = @import("common.zig").panic; comptime { if (builtin.os.tag == .windows) { // Default stack-probe functions emitted by LLVM - if (is_mingw) { + if (builtin.target.isMinGW()) { @export(&_chkstk, .{ .name = "_alloca", .linkage = linkage }); @export(&___chkstk_ms, .{ .name = "___chkstk_ms", .linkage = linkage }); - if (arch.isAARCH64()) { + if (arch == .thumb or arch == .aarch64) { @export(&__chkstk, .{ .name = "__chkstk", .linkage = linkage }); } } else if (!builtin.link_libc) { @@ -100,6 +97,35 @@ fn win_probe_stack_only() void { @setRuntimeSafety(false); switch (arch) { + .thumb => { + asm volatile ( + \\ lsl r4, r4, #2 + \\ mov r12, sp + \\ push {r5, r6} + \\ mov r5, r4 + \\1: + \\ sub r12, r12, #4096 + \\ subs r5, r5, #4096 + \\ ldr r6, [r12] + \\ bgt 1b + \\ pop {r5, r6} + \\ bx lr + ); + }, + .aarch64 => { + asm volatile ( + \\ lsl x16, x15, #4 + \\ mov x17, sp + \\1: + \\ + \\ sub x17, x17, 4096 + \\ subs x16, x16, 4096 + \\ ldr xzr, [x17] + \\ b.gt 1b + \\ + \\ ret + ); + }, .x86_64 => { asm volatile ( \\ push %%rcx @@ -144,21 +170,6 @@ fn win_probe_stack_only() void { }, else => {}, } - if (comptime arch.isAARCH64()) { - // NOTE: page size hardcoded to 4096 for now - asm volatile ( - \\ lsl x16, x15, #4 - \\ mov x17, sp - \\1: - \\ - \\ sub x17, x17, 4096 - \\ subs x16, x16, 4096 - \\ ldr xzr, [x17] - \\ b.gt 1b - \\ - \\ ret - ); - } unreachable; } @@ -240,7 +251,7 @@ pub fn _chkstk() callconv(.Naked) void { } pub fn __chkstk() callconv(.Naked) void { @setRuntimeSafety(false); - if (comptime arch.isAARCH64()) { + if (arch == .thumb or arch == .aarch64) { @call(.always_inline, win_probe_stack_only, .{}); } else switch (arch) { .x86 => @call(.always_inline, win_probe_stack_adjust_sp, .{}), diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index d585bcb94d..882526c049 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -603,7 +603,7 @@ pub const VaList = switch (builtin.cpu.arch) { .ios, .macos, .tvos, .watchos, .visionos => *u8, else => @compileError("disabled due to miscompilations"), // VaListAarch64, }, - .arm => switch (builtin.os.tag) { + .arm, .armeb, .thumb, .thumbeb => switch (builtin.os.tag) { .ios, .macos, .tvos, .watchos, .visionos => *u8, else => *anyopaque, }, diff --git a/lib/std/debug.zig b/lib/std/debug.zig index 4424bb1af1..a73c8e9668 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -789,7 +789,7 @@ pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const w } var i: usize = 0; - var image_base: usize = undefined; + var image_base: windows.DWORD64 = undefined; var history_table: windows.UNWIND_HISTORY_TABLE = std.mem.zeroes(windows.UNWIND_HISTORY_TABLE); while (i < addresses.len) : (i += 1) { @@ -809,7 +809,7 @@ pub noinline fn walkStackWindows(addresses: []usize, existing_context: ?*const w ); } else { // leaf function - context.setIp(@as(*u64, @ptrFromInt(current_regs.sp)).*); + context.setIp(@as(*usize, @ptrFromInt(current_regs.sp)).*); context.setSp(current_regs.sp + @sizeOf(usize)); } diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index e06a3ff02c..d277361352 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -2123,6 +2123,10 @@ pub fn teb() *TEB { ); } }, + .thumb => asm ( + \\ mrc p15, 0, %[ptr], c13, c0, 2 + : [ptr] "=r" (-> *TEB), + ), .aarch64 => asm ( \\ mov %[ptr], x18 : [ptr] "=r" (-> *TEB), @@ -4120,6 +4124,10 @@ pub const XMM_SAVE_AREA32 = switch (native_arch) { }; pub const NEON128 = switch (native_arch) { + .thumb => extern struct { + Low: ULONGLONG, + High: LONGLONG, + }, .aarch64 => extern union { DUMMYSTRUCTNAME: extern struct { Low: ULONGLONG, @@ -4248,6 +4256,54 @@ pub const CONTEXT = switch (native_arch) { ctx.Rsp = sp; } }, + .thumb => extern struct { + ContextFlags: ULONG, + R0: ULONG, + R1: ULONG, + R2: ULONG, + R3: ULONG, + R4: ULONG, + R5: ULONG, + R6: ULONG, + R7: ULONG, + R8: ULONG, + R9: ULONG, + R10: ULONG, + R11: ULONG, + R12: ULONG, + Sp: ULONG, + Lr: ULONG, + Pc: ULONG, + Cpsr: ULONG, + Fpcsr: ULONG, + Padding: ULONG, + DUMMYUNIONNAME: extern union { + Q: [16]NEON128, + D: [32]ULONGLONG, + S: [32]ULONG, + }, + Bvr: [8]ULONG, + Bcr: [8]ULONG, + Wvr: [1]ULONG, + Wcr: [1]ULONG, + Padding2: [2]ULONG, + + pub fn getRegs(ctx: *const CONTEXT) struct { bp: usize, ip: usize, sp: usize } { + return .{ + .bp = ctx.DUMMYUNIONNAME.S[11], + .ip = ctx.Pc, + .sp = ctx.Sp, + }; + } + + pub fn setIp(ctx: *CONTEXT, ip: usize) void { + ctx.Pc = ip; + } + + pub fn setSp(ctx: *CONTEXT, sp: usize) void { + ctx.Sp = sp; + } + }, .aarch64 => extern struct { ContextFlags: ULONG align(16), Cpsr: ULONG, @@ -4322,6 +4378,23 @@ pub const RUNTIME_FUNCTION = switch (native_arch) { EndAddress: DWORD, UnwindData: DWORD, }, + .thumb => extern struct { + BeginAddress: DWORD, + DUMMYUNIONNAME: extern union { + UnwindData: DWORD, + DUMMYSTRUCTNAME: packed struct { + Flag: u2, + FunctionLength: u11, + Ret: u2, + H: u1, + Reg: u3, + R: u1, + L: u1, + C: u1, + StackAdjust: u10, + }, + }, + }, .aarch64 => extern struct { BeginAddress: DWORD, DUMMYUNIONNAME: extern union { @@ -4345,6 +4418,25 @@ pub const KNONVOLATILE_CONTEXT_POINTERS = switch (native_arch) { FloatingContext: [16]?*M128A, IntegerContext: [16]?*ULONG64, }, + .thumb => extern struct { + R4: ?*DWORD, + R5: ?*DWORD, + R6: ?*DWORD, + R7: ?*DWORD, + R8: ?*DWORD, + R9: ?*DWORD, + R10: ?*DWORD, + R11: ?*DWORD, + Lr: ?*DWORD, + D8: ?*ULONGLONG, + D9: ?*ULONGLONG, + D10: ?*ULONGLONG, + D11: ?*ULONGLONG, + D12: ?*ULONGLONG, + D13: ?*ULONGLONG, + D14: ?*ULONGLONG, + D15: ?*ULONGLONG, + }, .aarch64 => extern struct { X19: ?*DWORD64, X20: ?*DWORD64, diff --git a/lib/std/zig/WindowsSdk.zig b/lib/std/zig/WindowsSdk.zig index caa389b010..1e1f0f1629 100644 --- a/lib/std/zig/WindowsSdk.zig +++ b/lib/std/zig/WindowsSdk.zig @@ -580,10 +580,10 @@ pub const Installation = struct { defer options_key.closeKey(); const option_name = comptime switch (builtin.target.cpu.arch) { - .arm, .armeb => "OptionId.DesktopCPParm", + .thumb => "OptionId.DesktopCPParm", .aarch64 => "OptionId.DesktopCPParm64", - .x86_64 => "OptionId.DesktopCPPx64", .x86 => "OptionId.DesktopCPPx86", + .x86_64 => "OptionId.DesktopCPPx64", else => |tag| @compileError("Windows SDK cannot be detected on architecture " ++ tag), }; @@ -824,10 +824,10 @@ const MsvcLibDir = struct { try lib_dir_buf.appendSlice("VC\\Tools\\MSVC\\"); try lib_dir_buf.appendSlice(default_tools_version); const folder_with_arch = "\\Lib\\" ++ comptime switch (builtin.target.cpu.arch) { + .thumb => "arm", + .aarch64 => "arm64", .x86 => "x86", .x86_64 => "x64", - .arm, .armeb => "arm", - .aarch64 => "arm64", else => |tag| @compileError("MSVC lib dir cannot be detected on architecture " ++ tag), }; try lib_dir_buf.appendSlice(folder_with_arch); @@ -909,10 +909,10 @@ const MsvcLibDir = struct { } const folder_with_arch = "\\Lib\\" ++ comptime switch (builtin.target.cpu.arch) { + .thumb => "arm", + .aarch64 => "arm64", .x86 => "x86", .x86_64 => "x64", - .arm, .armeb => "arm", - .aarch64 => "arm64", else => |tag| @compileError("MSVC lib dir cannot be detected on architecture " ++ tag), }; @@ -977,10 +977,10 @@ const MsvcLibDir = struct { errdefer base_path.deinit(); const folder_with_arch = "\\VC\\lib\\" ++ comptime switch (builtin.target.cpu.arch) { + .thumb => "arm", + .aarch64 => "arm64", .x86 => "", //x86 is in the root of the Lib folder .x86_64 => "amd64", - .arm, .armeb => "arm", - .aarch64 => "arm64", else => |tag| @compileError("MSVC lib dir cannot be detected on architecture " ++ tag), }; try base_path.appendSlice(folder_with_arch); diff --git a/lib/std/zig/target.zig b/lib/std/zig/target.zig index b248f21d6a..2a3652feb4 100644 --- a/lib/std/zig/target.zig +++ b/lib/std/zig/target.zig @@ -32,7 +32,7 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .thumbeb, .os = .linux, .abi = .gnueabihf }, .{ .arch = .thumbeb, .os = .linux, .abi = .musleabi }, .{ .arch = .thumbeb, .os = .linux, .abi = .musleabihf }, - .{ .arch = .arm, .os = .windows, .abi = .gnu }, + .{ .arch = .thumb, .os = .windows, .abi = .gnu }, .{ .arch = .csky, .os = .linux, .abi = .gnueabi, .glibc_min = .{ .major = 2, .minor = 29, .patch = 0 } }, .{ .arch = .csky, .os = .linux, .abi = .gnueabihf, .glibc_min = .{ .major = 2, .minor = 29, .patch = 0 } }, .{ .arch = .x86, .os = .linux, .abi = .gnu }, diff --git a/src/link/Coff.zig b/src/link/Coff.zig index 81f9a29830..6bf47e2602 100644 --- a/src/link/Coff.zig +++ b/src/link/Coff.zig @@ -276,7 +276,7 @@ pub fn createEmpty( .image_base = options.image_base orelse switch (output_mode) { .Exe => switch (target.cpu.arch) { .aarch64 => 0x140000000, - .x86_64, .x86 => 0x400000, + .thumb, .x86_64, .x86 => 0x400000, else => unreachable, }, .Lib => 0x10000000, diff --git a/src/mingw.zig b/src/mingw.zig index 0cebc389e6..114c168765 100644 --- a/src/mingw.zig +++ b/src/mingw.zig @@ -95,7 +95,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile, prog_node: std.Progre }); } } - } else if (target.cpu.arch.isARM()) { + } else if (target.cpu.arch.isThumb()) { for (mingw32_arm32_src) |dep| { try c_source_files.append(.{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ @@ -139,7 +139,7 @@ fn add_cc_args( }); const target = comp.getTarget(); - if (target.cpu.arch.isARM() and target.ptrBitWidth() == 32) { + if (target.cpu.arch.isThumb()) { try args.append("-mfpu=vfp"); } @@ -222,10 +222,10 @@ pub fn buildImportLib(comp: *Compilation, lib_name: []const u8) !void { }); const target_defines = switch (target.cpu.arch) { + .thumb => "#define DEF_ARM32\n", + .aarch64 => "#define DEF_ARM64\n", .x86 => "#define DEF_I386\n", .x86_64 => "#define DEF_X64\n", - .arm, .armeb, .thumb, .thumbeb => "#define DEF_ARM32\n", - .aarch64, .aarch64_be => "#define DEF_ARM64\n", else => unreachable, }; @@ -321,10 +321,10 @@ fn findDef( lib_name: []const u8, ) ![]u8 { const lib_path = switch (target.cpu.arch) { + .thumb => "libarm32", + .aarch64 => "libarm64", .x86 => "lib32", .x86_64 => "lib64", - .arm, .armeb, .thumb, .thumbeb => "libarm32", - .aarch64, .aarch64_be => "libarm64", else => unreachable, };