Merge pull request #21174 from alexrp/win-arm

Change `arm-windows-gnu` to `thumb-windows-gnu`, plus some initial port work
This commit is contained in:
Andrew Kelley 2024-08-30 14:34:53 -07:00 committed by GitHub
commit a4cc43c42b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 148 additions and 44 deletions

View File

@ -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 });

View File

@ -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, .{}),

View File

@ -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,
},

View File

@ -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));
}

View File

@ -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,

View File

@ -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);

View File

@ -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 },

View File

@ -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,

View File

@ -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,
};