authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-07-31 01:56:43-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-07-31 03:49:21-04:00
log228c956377e4f33e45fad7e0ba5d9eb5073803a5
treec4731c4d85805cd6c5acf11e7b53d3d5443519c2
parent2ba787e3038d8776599fb968b3ddec6b7a62a3f3

std: finish cleanup up asm

This also required implementing the necessary syntax in the x86_64 backend.

35 files changed, 498 insertions(+), 418 deletions(-)

lib/c.zig+91-96
...@@ -200,72 +200,67 @@ fn clone() callconv(.Naked) void {...@@ -200,72 +200,67 @@ fn clone() callconv(.Naked) void {
200 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)200 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
201 // eax, ebx, ecx, edx, esi, edi201 // eax, ebx, ecx, edx, esi, edi
202 asm volatile (202 asm volatile (
203 \\ push %%ebp203 \\ pushl %%ebp
204 \\ mov %%esp,%%ebp204 \\ movl %%esp,%%ebp
205 \\ push %%ebx205 \\ pushl %%ebx
206 \\ push %%esi206 \\ pushl %%esi
207 \\ push %%edi207 \\ pushl %%edi
208 \\ // Setup the arguments208 \\ // Setup the arguments
209 \\ mov 16(%%ebp),%%ebx209 \\ movl 16(%%ebp),%%ebx
210 \\ mov 12(%%ebp),%%ecx210 \\ movl 12(%%ebp),%%ecx
211 \\ and $-16,%%ecx211 \\ andl $-16,%%ecx
212 \\ sub $20,%%ecx212 \\ subl $20,%%ecx
213 \\ mov 20(%%ebp),%%eax213 \\ movl 20(%%ebp),%%eax
214 \\ mov %%eax,4(%%ecx)214 \\ movl %%eax,4(%%ecx)
215 \\ mov 8(%%ebp),%%eax215 \\ movl 8(%%ebp),%%eax
216 \\ mov %%eax,0(%%ecx)216 \\ movl %%eax,0(%%ecx)
217 \\ mov 24(%%ebp),%%edx217 \\ movl 24(%%ebp),%%edx
218 \\ mov 28(%%ebp),%%esi218 \\ movl 28(%%ebp),%%esi
219 \\ mov 32(%%ebp),%%edi219 \\ movl 32(%%ebp),%%edi
220 \\ mov $120,%%eax220 \\ movl $120,%%eax
221 \\ int $128221 \\ int $128
222 \\ test %%eax,%%eax222 \\ testl %%eax,%%eax
223 \\ jnz 1f223 \\ jnz 1f
224 \\ pop %%eax224 \\ popl %%eax
225 \\ xor %%ebp,%%ebp225 \\ xorl %%ebp,%%ebp
226 \\ call *%%eax226 \\ calll *%%eax
227 \\ mov %%eax,%%ebx227 \\ movl %%eax,%%ebx
228 \\ xor %%eax,%%eax228 \\ movl $1,%%eax
229 \\ inc %%eax
230 \\ int $128229 \\ int $128
231 \\ hlt
232 \\1:230 \\1:
233 \\ pop %%edi231 \\ popl %%edi
234 \\ pop %%esi232 \\ popl %%esi
235 \\ pop %%ebx233 \\ popl %%ebx
236 \\ pop %%ebp234 \\ popl %%ebp
237 \\ ret235 \\ retl
238 );236 );
239 },237 },
240 .x86_64 => {238 .x86_64 => {
241 asm volatile (239 asm volatile (
242 \\ xor %%eax,%%eax240 \\ movl $56,%%eax // SYS_clone
243 \\ mov $56,%%al // SYS_clone241 \\ movq %%rdi,%%r11
244 \\ mov %%rdi,%%r11242 \\ movq %%rdx,%%rdi
245 \\ mov %%rdx,%%rdi243 \\ movq %%r8,%%rdx
246 \\ mov %%r8,%%rdx244 \\ movq %%r9,%%r8
247 \\ mov %%r9,%%r8245 \\ movq 8(%%rsp),%%r10
248 \\ mov 8(%%rsp),%%r10246 \\ movq %%r11,%%r9
249 \\ mov %%r11,%%r9247 \\ andq $-16,%%rsi
250 \\ and $-16,%%rsi248 \\ subq $8,%%rsi
251 \\ sub $8,%%rsi249 \\ movq %%rcx,(%%rsi)
252 \\ mov %%rcx,(%%rsi)
253 \\ syscall250 \\ syscall
254 \\ test %%eax,%%eax251 \\ testq %%rax,%%rax
255 \\ jnz 1f252 \\ jnz 1f
256 \\ xor %%ebp,%%ebp253 \\ xorl %%ebp,%%ebp
257 \\ pop %%rdi254 \\ popq %%rdi
258 \\ call *%%r9255 \\ callq *%%r9
259 \\ mov %%eax,%%edi256 \\ movl %%eax,%%edi
260 \\ xor %%eax,%%eax257 \\ movl $60,%%eax // SYS_exit
261 \\ mov $60,%%al // SYS_exit
262 \\ syscall258 \\ syscall
263 \\ hlt
264 \\1: ret259 \\1: ret
265 \\260 \\
266 );261 );
267 },262 },
268 .aarch64 => {263 .aarch64, .aarch64_be => {
269 // __clone(func, stack, flags, arg, ptid, tls, ctid)264 // __clone(func, stack, flags, arg, ptid, tls, ctid)
270 // x0, x1, w2, x3, x4, x5, x6265 // x0, x1, w2, x3, x4, x5, x6
271266
...@@ -400,69 +395,69 @@ fn clone() callconv(.Naked) void {...@@ -400,69 +395,69 @@ fn clone() callconv(.Naked) void {
400 \\ syscall395 \\ syscall
401 );396 );
402 },397 },
403 .powerpc => {398 .powerpc, .powerpcle => {
404 // __clone(func, stack, flags, arg, ptid, tls, ctid)399 // __clone(func, stack, flags, arg, ptid, tls, ctid)
405 // 3, 4, 5, 6, 7, 8, 9400 // 3, 4, 5, 6, 7, 8, 9
406401
407 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)402 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
408 // 0 3, 4, 5, 6, 7403 // 0 3, 4, 5, 6, 7
409 asm volatile (404 asm volatile (
410 \\# store non-volatile regs r30, r31 on stack in order to put our405 \\ # store non-volatile regs r30, r31 on stack in order to put our
411 \\# start func and its arg there406 \\ # start func and its arg there
412 \\stwu 30, -16(1)407 \\ stwu 30, -16(1)
413 \\stw 31, 4(1)408 \\ stw 31, 4(1)
414 \\409 \\
415 \\# save r3 (func) into r30, and r6(arg) into r31410 \\ # save r3 (func) into r30, and r6(arg) into r31
416 \\mr 30, 3411 \\ mr 30, 3
417 \\mr 31, 6412 \\ mr 31, 6
418 \\413 \\
419 \\# create initial stack frame for new thread414 \\ # create initial stack frame for new thread
420 \\clrrwi 4, 4, 4415 \\ clrrwi 4, 4, 4
421 \\li 0, 0416 \\ li 0, 0
422 \\stwu 0, -16(4)417 \\ stwu 0, -16(4)
423 \\418 \\
424 \\#move c into first arg419 \\ #move c into first arg
425 \\mr 3, 5420 \\ mr 3, 5
426 \\#mr 4, 4421 \\ #mr 4, 4
427 \\mr 5, 7422 \\ mr 5, 7
428 \\mr 6, 8423 \\ mr 6, 8
429 \\mr 7, 9424 \\ mr 7, 9
430 \\425 \\
431 \\# move syscall number into r0426 \\ # move syscall number into r0
432 \\li 0, 120427 \\ li 0, 120
433 \\428 \\
434 \\sc429 \\ sc
435 \\430 \\
436 \\# check for syscall error431 \\ # check for syscall error
437 \\bns+ 1f # jump to label 1 if no summary overflow.432 \\ bns+ 1f # jump to label 1 if no summary overflow.
438 \\#else433 \\ #else
439 \\neg 3, 3 #negate the result (errno)434 \\ neg 3, 3 #negate the result (errno)
440 \\1:435 \\ 1:
441 \\# compare sc result with 0436 \\ # compare sc result with 0
442 \\cmpwi cr7, 3, 0437 \\ cmpwi cr7, 3, 0
443 \\438 \\
444 \\# if not 0, jump to end439 \\ # if not 0, jump to end
445 \\bne cr7, 2f440 \\ bne cr7, 2f
446 \\441 \\
447 \\#else: we're the child442 \\ #else: we're the child
448 \\#call funcptr: move arg (d) into r3443 \\ #call funcptr: move arg (d) into r3
449 \\mr 3, 31444 \\ mr 3, 31
450 \\#move r30 (funcptr) into CTR reg445 \\ #move r30 (funcptr) into CTR reg
451 \\mtctr 30446 \\ mtctr 30
452 \\# call CTR reg447 \\ # call CTR reg
453 \\bctrl448 \\ bctrl
454 \\# mov SYS_exit into r0 (the exit param is already in r3)449 \\ # mov SYS_exit into r0 (the exit param is already in r3)
455 \\li 0, 1450 \\ li 0, 1
456 \\sc451 \\ sc
457 \\452 \\
458 \\2:453 \\ 2:
459 \\454 \\
460 \\# restore stack455 \\ # restore stack
461 \\lwz 30, 0(1)456 \\ lwz 30, 0(1)
462 \\lwz 31, 4(1)457 \\ lwz 31, 4(1)
463 \\addi 1, 1, 16458 \\ addi 1, 1, 16
464 \\459 \\
465 \\blr460 \\ blr
466 );461 );
467 },462 },
468 .powerpc64, .powerpc64le => {463 .powerpc64, .powerpc64le => {
lib/compiler_rt/arm.zig+1-1
...@@ -9,7 +9,7 @@ pub const panic = common.panic;...@@ -9,7 +9,7 @@ pub const panic = common.panic;
99
10comptime {10comptime {
11 if (!builtin.is_test) {11 if (!builtin.is_test) {
12 if (arch.isARM() or arch.isThumb()) {12 if (arch.isArmOrThumb()) {
13 @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = common.linkage, .visibility = common.visibility });13 @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = common.linkage, .visibility = common.visibility });
14 @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = common.linkage, .visibility = common.visibility });14 @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = common.linkage, .visibility = common.visibility });
15 @export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = common.linkage, .visibility = common.visibility });15 @export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = common.linkage, .visibility = common.visibility });
lib/compiler_rt/clzsi2_test.zig+1-1
...@@ -268,7 +268,7 @@ test "clzsi2" {...@@ -268,7 +268,7 @@ test "clzsi2" {
268 try test__clzsi2(0xFE000000, 0);268 try test__clzsi2(0xFE000000, 0);
269 try test__clzsi2(0xFF000000, 0);269 try test__clzsi2(0xFF000000, 0);
270 // arm and thumb1 assume input a != 0270 // arm and thumb1 assume input a != 0
271 if (!builtin.cpu.arch.isARM() and !builtin.cpu.arch.isThumb())271 if (!builtin.cpu.arch.isArmOrThumb())
272 try test__clzsi2(0x00000000, 32);272 try test__clzsi2(0x00000000, 32);
273 try test__clzsi2(0x00000001, 31);273 try test__clzsi2(0x00000001, 31);
274 try test__clzsi2(0x00000002, 30);274 try test__clzsi2(0x00000002, 30);
lib/std/builtin.zig+1-1
...@@ -568,7 +568,7 @@ pub const VaListX86_64 = extern struct {...@@ -568,7 +568,7 @@ pub const VaListX86_64 = extern struct {
568/// This data structure is used by the Zig language code generation and568/// This data structure is used by the Zig language code generation and
569/// therefore must be kept in sync with the compiler implementation.569/// therefore must be kept in sync with the compiler implementation.
570pub const VaList = switch (builtin.cpu.arch) {570pub const VaList = switch (builtin.cpu.arch) {
571 .aarch64 => switch (builtin.os.tag) {571 .aarch64, .aarch64_be => switch (builtin.os.tag) {
572 .windows => *u8,572 .windows => *u8,
573 .ios, .macos, .tvos, .watchos => *u8,573 .ios, .macos, .tvos, .watchos => *u8,
574 else => @compileError("disabled due to miscompilations"), // VaListAarch64,574 else => @compileError("disabled due to miscompilations"), // VaListAarch64,
lib/std/os/linux.zig+6-8
...@@ -35,13 +35,13 @@ const syscall_bits = switch (native_arch) {...@@ -35,13 +35,13 @@ const syscall_bits = switch (native_arch) {
35const arch_bits = switch (native_arch) {35const arch_bits = switch (native_arch) {
36 .x86 => @import("linux/x86.zig"),36 .x86 => @import("linux/x86.zig"),
37 .x86_64 => @import("linux/x86_64.zig"),37 .x86_64 => @import("linux/x86_64.zig"),
38 .aarch64 => @import("linux/arm64.zig"),38 .aarch64, .aarch64_be => @import("linux/arm64.zig"),
39 .arm, .thumb => @import("linux/arm-eabi.zig"),39 .arm, .thumb => @import("linux/arm-eabi.zig"),
40 .riscv64 => @import("linux/riscv64.zig"),40 .riscv64 => @import("linux/riscv64.zig"),
41 .sparc64 => @import("linux/sparc64.zig"),41 .sparc64 => @import("linux/sparc64.zig"),
42 .mips, .mipsel => @import("linux/mips.zig"),42 .mips, .mipsel => @import("linux/mips.zig"),
43 .mips64, .mips64el => @import("linux/mips64.zig"),43 .mips64, .mips64el => @import("linux/mips64.zig"),
44 .powerpc => @import("linux/powerpc.zig"),44 .powerpc, .powerpcle => @import("linux/powerpc.zig"),
45 .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"),45 .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"),
46 else => struct {},46 else => struct {},
47};47};
...@@ -98,13 +98,13 @@ pub const syscalls = @import("linux/syscalls.zig");...@@ -98,13 +98,13 @@ pub const syscalls = @import("linux/syscalls.zig");
98pub const SYS = switch (@import("builtin").cpu.arch) {98pub const SYS = switch (@import("builtin").cpu.arch) {
99 .x86 => syscalls.X86,99 .x86 => syscalls.X86,
100 .x86_64 => syscalls.X64,100 .x86_64 => syscalls.X64,
101 .aarch64 => syscalls.Arm64,101 .aarch64, .aarch64_be => syscalls.Arm64,
102 .arm, .thumb => syscalls.Arm,102 .arm, .thumb => syscalls.Arm,
103 .riscv64 => syscalls.RiscV64,103 .riscv64 => syscalls.RiscV64,
104 .sparc64 => syscalls.Sparc64,104 .sparc64 => syscalls.Sparc64,
105 .mips, .mipsel => syscalls.Mips,105 .mips, .mipsel => syscalls.Mips,
106 .mips64, .mips64el => syscalls.Mips64,106 .mips64, .mips64el => syscalls.Mips64,
107 .powerpc => syscalls.PowerPC,107 .powerpc, .powerpcle => syscalls.PowerPC,
108 .powerpc64, .powerpc64le => syscalls.PowerPC64,108 .powerpc64, .powerpc64le => syscalls.PowerPC64,
109 else => @compileError("The Zig Standard Library is missing syscall definitions for the target CPU architecture"),109 else => @compileError("The Zig Standard Library is missing syscall definitions for the target CPU architecture"),
110};110};
...@@ -1176,14 +1176,12 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact...@@ -1176,14 +1176,12 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact
1176 const mask_size = @sizeOf(@TypeOf(ksa.mask));1176 const mask_size = @sizeOf(@TypeOf(ksa.mask));
11771177
1178 if (act) |new| {1178 if (act) |new| {
1179 const restore_rt_ptr = &restore_rt;1179 const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) &restore_rt else &restore;
1180 const restore_ptr = &restore;
1181 const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) restore_rt_ptr else restore_ptr;
1182 ksa = k_sigaction{1180 ksa = k_sigaction{
1183 .handler = new.handler.handler,1181 .handler = new.handler.handler,
1184 .flags = new.flags | SA.RESTORER,1182 .flags = new.flags | SA.RESTORER,
1185 .mask = undefined,1183 .mask = undefined,
1186 .restorer = @as(k_sigaction_funcs.restorer, @ptrCast(restorer_fn)),1184 .restorer = @ptrCast(restorer_fn),
1187 };1185 };
1188 @memcpy(@as([*]u8, @ptrCast(&ksa.mask))[0..mask_size], @as([*]const u8, @ptrCast(&new.mask)));1186 @memcpy(@as([*]u8, @ptrCast(&ksa.mask))[0..mask_size], @as([*]const u8, @ptrCast(&new.mask)));
1189 }1187 }
lib/std/os/linux/arm-eabi.zig+22-26
...@@ -103,44 +103,40 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;...@@ -103,44 +103,40 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;
103/// This matches the libc clone function.103/// This matches the libc clone function.
104pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;104pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
105105
106pub fn restore() callconv(.Naked) void {106pub fn restore() callconv(.Naked) noreturn {
107 if (@import("builtin").zig_backend == .stage2_c) {107 switch (@import("builtin").zig_backend) {
108 asm volatile (108 .stage2_c => asm volatile (
109 \\ mov r7, %[number]109 \\ mov r7, %[number]
110 \\ svc #0110 \\ svc #0
111 \\ bx lr
112 :111 :
113 : [number] "i" (@intFromEnum(SYS.sigreturn)),112 : [number] "I" (@intFromEnum(SYS.sigreturn)),
114 : "memory"113 : "memory"
115 );114 ),
116 unreachable;115 else => asm volatile (
116 \\ svc #0
117 :
118 : [number] "{r7}" (@intFromEnum(SYS.sigreturn)),
119 : "memory"
120 ),
117 }121 }
118
119 asm volatile ("svc #0"
120 :
121 : [number] "{r7}" (@intFromEnum(SYS.sigreturn)),
122 : "memory"
123 );
124}122}
125123
126pub fn restore_rt() callconv(.Naked) void {124pub fn restore_rt() callconv(.Naked) noreturn {
127 if (@import("builtin").zig_backend == .stage2_c) {125 switch (@import("builtin").zig_backend) {
128 asm volatile (126 .stage2_c => asm volatile (
129 \\ mov r7, %[number]127 \\ mov r7, %[number]
130 \\ svc #0128 \\ svc #0
131 \\ bx lr
132 :129 :
133 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),130 : [number] "I" (@intFromEnum(SYS.rt_sigreturn)),
134 : "memory"131 : "memory"
135 );132 ),
136 unreachable;133 else => asm volatile (
134 \\ svc #0
135 :
136 : [number] "{r7}" (@intFromEnum(SYS.rt_sigreturn)),
137 : "memory"
138 ),
137 }139 }
138
139 asm volatile ("svc #0"
140 :
141 : [number] "{r7}" (@intFromEnum(SYS.rt_sigreturn)),
142 : "memory"
143 );
144}140}
145141
146pub const MMAP2_UNIT = 4096;142pub const MMAP2_UNIT = 4096;
lib/std/os/linux/arm64.zig+10-13
...@@ -105,25 +105,22 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *...@@ -105,25 +105,22 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *
105105
106pub const restore = restore_rt;106pub const restore = restore_rt;
107107
108pub fn restore_rt() callconv(.Naked) void {108pub fn restore_rt() callconv(.Naked) noreturn {
109 if (@import("builtin").zig_backend == .stage2_c) {109 switch (@import("builtin").zig_backend) {
110 asm volatile (110 .stage2_c => asm volatile (
111 \\ mov x8, %[number]111 \\ mov x8, %[number]
112 \\ svc #0112 \\ svc #0
113 \\ ret
114 :113 :
115 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),114 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
116 : "memory", "cc"115 : "memory", "cc"
117 );116 ),
118 unreachable;117 else => asm volatile (
118 \\ svc #0
119 :
120 : [number] "{x8}" (@intFromEnum(SYS.rt_sigreturn)),
121 : "memory", "cc"
122 ),
119 }123 }
120
121 asm volatile (
122 \\ svc #0
123 :
124 : [number] "{x8}" (@intFromEnum(SYS.rt_sigreturn)),
125 : "memory", "cc"
126 );
127}124}
128125
129pub const O = struct {126pub const O = struct {
lib/std/os/linux/mips.zig+6-4
...@@ -195,16 +195,18 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;...@@ -195,16 +195,18 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;
195/// This matches the libc clone function.195/// This matches the libc clone function.
196pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;196pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
197197
198pub fn restore() callconv(.Naked) void {198pub fn restore() callconv(.Naked) noreturn {
199 return asm volatile ("syscall"199 asm volatile (
200 \\ syscall
200 :201 :
201 : [number] "{$2}" (@intFromEnum(SYS.sigreturn)),202 : [number] "{$2}" (@intFromEnum(SYS.sigreturn)),
202 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"203 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"
203 );204 );
204}205}
205206
206pub fn restore_rt() callconv(.Naked) void {207pub fn restore_rt() callconv(.Naked) noreturn {
207 return asm volatile ("syscall"208 asm volatile (
209 \\ syscall
208 :210 :
209 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),211 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),
210 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"212 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"
lib/std/os/linux/mips64.zig+6-4
...@@ -180,16 +180,18 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;...@@ -180,16 +180,18 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;
180/// This matches the libc clone function.180/// This matches the libc clone function.
181pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;181pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
182182
183pub fn restore() callconv(.Naked) void {183pub fn restore() callconv(.Naked) noreturn {
184 return asm volatile ("syscall"184 asm volatile (
185 \\ syscall
185 :186 :
186 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),187 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),
187 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"188 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"
188 );189 );
189}190}
190191
191pub fn restore_rt() callconv(.Naked) void {192pub fn restore_rt() callconv(.Naked) noreturn {
192 return asm volatile ("syscall"193 asm volatile (
194 \\ syscall
193 :195 :
194 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),196 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),
195 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"197 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"
lib/std/os/linux/powerpc.zig+3-2
...@@ -133,8 +133,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:...@@ -133,8 +133,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:
133133
134pub const restore = restore_rt;134pub const restore = restore_rt;
135135
136pub fn restore_rt() callconv(.Naked) void {136pub fn restore_rt() callconv(.Naked) noreturn {
137 return asm volatile ("sc"137 asm volatile (
138 \\ sc
138 :139 :
139 : [number] "{r0}" (@intFromEnum(SYS.rt_sigreturn)),140 : [number] "{r0}" (@intFromEnum(SYS.rt_sigreturn)),
140 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"141 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
lib/std/os/linux/powerpc64.zig+3-2
...@@ -133,8 +133,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:...@@ -133,8 +133,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:
133133
134pub const restore = restore_rt;134pub const restore = restore_rt;
135135
136pub fn restore_rt() callconv(.Naked) void {136pub fn restore_rt() callconv(.Naked) noreturn {
137 return asm volatile ("sc"137 asm volatile (
138 \\ sc
138 :139 :
139 : [number] "{r0}" (@intFromEnum(SYS.rt_sigreturn)),140 : [number] "{r0}" (@intFromEnum(SYS.rt_sigreturn)),
140 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"141 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
lib/std/os/linux/riscv64.zig+3-2
...@@ -101,8 +101,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *...@@ -101,8 +101,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *
101101
102pub const restore = restore_rt;102pub const restore = restore_rt;
103103
104pub fn restore_rt() callconv(.Naked) void {104pub fn restore_rt() callconv(.Naked) noreturn {
105 return asm volatile ("ecall"105 asm volatile (
106 \\ ecall
106 :107 :
107 : [number] "{x17}" (@intFromEnum(SYS.rt_sigreturn)),108 : [number] "{x17}" (@intFromEnum(SYS.rt_sigreturn)),
108 : "memory"109 : "memory"
lib/std/os/linux/thumb.zig+4-4
...@@ -141,8 +141,8 @@ pub fn syscall6(...@@ -141,8 +141,8 @@ pub fn syscall6(
141 );141 );
142}142}
143143
144pub fn restore() callconv(.Naked) void {144pub fn restore() callconv(.Naked) noreturn {
145 return asm volatile (145 asm volatile (
146 \\ mov r7, %[number]146 \\ mov r7, %[number]
147 \\ svc #0147 \\ svc #0
148 :148 :
...@@ -150,8 +150,8 @@ pub fn restore() callconv(.Naked) void {...@@ -150,8 +150,8 @@ pub fn restore() callconv(.Naked) void {
150 );150 );
151}151}
152152
153pub fn restore_rt() callconv(.Naked) void {153pub fn restore_rt() callconv(.Naked) noreturn {
154 return asm volatile (154 asm volatile (
155 \\ mov r7, %[number]155 \\ mov r7, %[number]
156 \\ svc #0156 \\ svc #0
157 :157 :
lib/std/os/linux/tls.zig+3-3
...@@ -48,7 +48,7 @@ const TLSVariant = enum {...@@ -48,7 +48,7 @@ const TLSVariant = enum {
48};48};
4949
50const tls_variant = switch (native_arch) {50const tls_variant = switch (native_arch) {
51 .arm, .armeb, .thumb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .mips64, .mips64el, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI,51 .arm, .armeb, .thumb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .mips64, .mips64el, .powerpc, .powerpcle, .powerpc64, .powerpc64le => TLSVariant.VariantI,
52 .x86_64, .x86, .sparc64 => TLSVariant.VariantII,52 .x86_64, .x86, .sparc64 => TLSVariant.VariantII,
53 else => @compileError("undefined tls_variant for this architecture"),53 else => @compileError("undefined tls_variant for this architecture"),
54};54};
...@@ -140,7 +140,7 @@ pub fn setThreadPointer(addr: usize) void {...@@ -140,7 +140,7 @@ pub fn setThreadPointer(addr: usize) void {
140 const rc = std.os.linux.syscall2(.arch_prctl, std.os.linux.ARCH.SET_FS, addr);140 const rc = std.os.linux.syscall2(.arch_prctl, std.os.linux.ARCH.SET_FS, addr);
141 assert(rc == 0);141 assert(rc == 0);
142 },142 },
143 .aarch64 => {143 .aarch64, .aarch64_be => {
144 asm volatile (144 asm volatile (
145 \\ msr tpidr_el0, %[addr]145 \\ msr tpidr_el0, %[addr]
146 :146 :
...@@ -162,7 +162,7 @@ pub fn setThreadPointer(addr: usize) void {...@@ -162,7 +162,7 @@ pub fn setThreadPointer(addr: usize) void {
162 const rc = std.os.linux.syscall1(.set_thread_area, addr);162 const rc = std.os.linux.syscall1(.set_thread_area, addr);
163 assert(rc == 0);163 assert(rc == 0);
164 },164 },
165 .powerpc => {165 .powerpc, .powerpcle => {
166 asm volatile (166 asm volatile (
167 \\ mr 2, %[addr]167 \\ mr 2, %[addr]
168 :168 :
lib/std/os/linux/x86.zig+23-28
...@@ -123,46 +123,40 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;...@@ -123,46 +123,40 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;
123/// This matches the libc clone function.123/// This matches the libc clone function.
124pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;124pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
125125
126pub fn restore() callconv(.Naked) void {126pub fn restore() callconv(.Naked) noreturn {
127 if (@import("builtin").zig_backend == .stage2_c) {127 switch (@import("builtin").zig_backend) {
128 asm volatile (128 .stage2_c => asm volatile (
129 \\ movl %[number], %%eax129 \\ movl %[number], %%eax
130 \\ int $0x80130 \\ int $0x80
131 \\ retl
132 :131 :
133 : [number] "i" (@intFromEnum(SYS.sigreturn)),132 : [number] "i" (@intFromEnum(SYS.sigreturn)),
134 : "memory"133 : "memory"
135 );134 ),
136 unreachable;135 else => asm volatile (
136 \\ int $0x80
137 :
138 : [number] "{eax}" (@intFromEnum(SYS.sigreturn)),
139 : "memory"
140 ),
137 }141 }
138
139 asm volatile (
140 \\ int $0x80
141 :
142 : [number] "{eax}" (@intFromEnum(SYS.sigreturn)),
143 : "memory"
144 );
145}142}
146143
147pub fn restore_rt() callconv(.Naked) void {144pub fn restore_rt() callconv(.Naked) noreturn {
148 if (@import("builtin").zig_backend == .stage2_c) {145 switch (@import("builtin").zig_backend) {
149 asm volatile (146 .stage2_c => asm volatile (
150 \\ movl %[number], %%eax147 \\ movl %[number], %%eax
151 \\ int $0x80148 \\ int $0x80
152 \\ retl
153 :149 :
154 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),150 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
155 : "memory"151 : "memory"
156 );152 ),
157 unreachable;153 else => asm volatile (
154 \\ int $0x80
155 :
156 : [number] "{eax}" (@intFromEnum(SYS.rt_sigreturn)),
157 : "memory"
158 ),
158 }159 }
159
160 asm volatile (
161 \\ int $0x80
162 :
163 : [number] "{eax}" (@intFromEnum(SYS.rt_sigreturn)),
164 : "memory"
165 );
166}160}
167161
168pub const O = struct {162pub const O = struct {
...@@ -401,7 +395,7 @@ noinline fn getContextReturnAddress() usize {...@@ -401,7 +395,7 @@ noinline fn getContextReturnAddress() usize {
401 return @returnAddress();395 return @returnAddress();
402}396}
403397
404pub fn getContextInternal() callconv(.Naked) void {398pub fn getContextInternal() callconv(.Naked) usize {
405 asm volatile (399 asm volatile (
406 \\ movl $0, %[flags_offset:c](%%edx)400 \\ movl $0, %[flags_offset:c](%%edx)
407 \\ movl $0, %[link_offset:c](%%edx)401 \\ movl $0, %[link_offset:c](%%edx)
...@@ -439,6 +433,7 @@ pub fn getContextInternal() callconv(.Naked) void {...@@ -439,6 +433,7 @@ pub fn getContextInternal() callconv(.Naked) void {
439 \\0:433 \\0:
440 \\ popl %%esi434 \\ popl %%esi
441 \\ popl %%ebx435 \\ popl %%ebx
436 \\ retl
442 :437 :
443 : [flags_offset] "i" (@offsetOf(ucontext_t, "flags")),438 : [flags_offset] "i" (@offsetOf(ucontext_t, "flags")),
444 [link_offset] "i" (@offsetOf(ucontext_t, "link")),439 [link_offset] "i" (@offsetOf(ucontext_t, "link")),
...@@ -466,7 +461,7 @@ pub fn getContextInternal() callconv(.Naked) void {...@@ -466,7 +461,7 @@ pub fn getContextInternal() callconv(.Naked) void {
466pub inline fn getcontext(context: *ucontext_t) usize {461pub inline fn getcontext(context: *ucontext_t) usize {
467 // This method is used so that getContextInternal can control462 // This method is used so that getContextInternal can control
468 // its prologue in order to read ESP from a constant offset.463 // its prologue in order to read ESP from a constant offset.
469 // The unused &getContextInternal input is required so the function is included in the binary.464 // An aligned stack is not needed for getContextInternal.
470 var clobber_edx: usize = undefined;465 var clobber_edx: usize = undefined;
471 return asm volatile (466 return asm volatile (
472 \\ calll %[getContextInternal:P]467 \\ calll %[getContextInternal:P]
lib/std/os/linux/x86_64.zig+13-15
...@@ -107,25 +107,22 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:...@@ -107,25 +107,22 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:
107107
108pub const restore = restore_rt;108pub const restore = restore_rt;
109109
110pub fn restore_rt() callconv(.Naked) void {110pub fn restore_rt() callconv(.Naked) noreturn {
111 if (@import("builtin").zig_backend == .stage2_c) {111 switch (@import("builtin").zig_backend) {
112 asm volatile (112 .stage2_c => asm volatile (
113 \\ movl %[number], %%eax113 \\ movl %[number], %%eax
114 \\ syscall114 \\ syscall
115 \\ retq
116 :115 :
117 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),116 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
118 : "rcx", "r11", "memory"117 : "rcx", "r11", "memory"
119 );118 ),
120 unreachable;119 else => asm volatile (
120 \\ syscall
121 :
122 : [number] "{rax}" (@intFromEnum(SYS.rt_sigreturn)),
123 : "rcx", "r11", "memory"
124 ),
121 }125 }
122
123 asm volatile (
124 \\ syscall
125 :
126 : [number] "{rax}" (@intFromEnum(SYS.rt_sigreturn)),
127 : "rcx", "r11", "memory"
128 );
129}126}
130127
131pub const mode_t = usize;128pub const mode_t = usize;
...@@ -400,7 +397,7 @@ fn gpRegisterOffset(comptime reg_index: comptime_int) usize {...@@ -400,7 +397,7 @@ fn gpRegisterOffset(comptime reg_index: comptime_int) usize {
400 return @offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "gregs") + @sizeOf(usize) * reg_index;397 return @offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "gregs") + @sizeOf(usize) * reg_index;
401}398}
402399
403fn getContextInternal() callconv(.Naked) void {400fn getContextInternal() callconv(.Naked) usize {
404 // TODO: Read GS/FS registers?401 // TODO: Read GS/FS registers?
405 asm volatile (402 asm volatile (
406 \\ movq $0, %[flags_offset:c](%%rdi)403 \\ movq $0, %[flags_offset:c](%%rdi)
...@@ -444,6 +441,7 @@ fn getContextInternal() callconv(.Naked) void {...@@ -444,6 +441,7 @@ fn getContextInternal() callconv(.Naked) void {
444 \\ movl %[sigset_size], %%r10d441 \\ movl %[sigset_size], %%r10d
445 \\ syscall442 \\ syscall
446 \\0:443 \\0:
444 \\ retq
447 :445 :
448 : [flags_offset] "i" (@offsetOf(ucontext_t, "flags")),446 : [flags_offset] "i" (@offsetOf(ucontext_t, "flags")),
449 [link_offset] "i" (@offsetOf(ucontext_t, "link")),447 [link_offset] "i" (@offsetOf(ucontext_t, "link")),
...@@ -480,7 +478,7 @@ fn getContextInternal() callconv(.Naked) void {...@@ -480,7 +478,7 @@ fn getContextInternal() callconv(.Naked) void {
480pub inline fn getcontext(context: *ucontext_t) usize {478pub inline fn getcontext(context: *ucontext_t) usize {
481 // This method is used so that getContextInternal can control479 // This method is used so that getContextInternal can control
482 // its prologue in order to read RSP from a constant offset480 // its prologue in order to read RSP from a constant offset
483 // The unused &getContextInternal input is required so the function is included in the binary.481 // An aligned stack is not needed for getContextInternal.
484 var clobber_rdi: usize = undefined;482 var clobber_rdi: usize = undefined;
485 return asm volatile (483 return asm volatile (
486 \\ callq %[getContextInternal:P]484 \\ callq %[getContextInternal:P]
lib/std/start.zig+86-112
...@@ -101,7 +101,7 @@ fn main2() callconv(.C) c_int {...@@ -101,7 +101,7 @@ fn main2() callconv(.C) c_int {
101 return 0;101 return 0;
102}102}
103103
104fn _start2() callconv(.Naked) noreturn {104fn _start2() noreturn {
105 callMain2();105 callMain2();
106}106}
107107
...@@ -254,116 +254,92 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv...@@ -254,116 +254,92 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv
254}254}
255255
256fn _start() callconv(.Naked) noreturn {256fn _start() callconv(.Naked) noreturn {
257 switch (builtin.zig_backend) {257 asm volatile (switch (native_arch) {
258 .stage2_c => {258 .x86_64 =>
259 asm volatile (switch (native_arch) {259 \\ xorl %%ebp, %%ebp
260 .x86_64 =>260 \\ movq %%rsp, %[argc_argv_ptr]
261 \\ xorl %%ebp, %%ebp261 \\ andq $-16, %%rsp
262 \\ movq %%rsp, %[argc_argv_ptr]262 \\ callq %[posixCallMainAndExit:P]
263 \\ andq $-16, %%rsp263 ,
264 \\ callq %[posixCallMainAndExit:P]264 .x86 =>
265 ,265 \\ xorl %%ebp, %%ebp
266 .x86 =>266 \\ movl %%esp, %[argc_argv_ptr]
267 \\ xorl %%ebp, %%ebp267 \\ andl $-16, %%esp
268 \\ movl %%esp, %[argc_argv_ptr]268 \\ calll %[posixCallMainAndExit:P]
269 \\ andl $-16, %%esp269 ,
270 \\ calll %[posixCallMainAndExit:P]270 .aarch64, .aarch64_be =>
271 ,271 \\ mov fp, #0
272 .aarch64, .aarch64_be =>272 \\ mov lr, #0
273 \\ mov fp, #0273 \\ mov x0, sp
274 \\ mov lr, #0274 \\ str x0, %[argc_argv_ptr]
275 \\ mov x0, sp275 \\ b %[posixCallMainAndExit]
276 \\ str x0, %[argc_argv_ptr]276 ,
277 \\ b %[posixCallMainAndExit]277 .arm, .armeb, .thumb, .thumbeb =>
278 ,278 \\ mov fp, #0
279 .arm, .armeb, .thumb =>279 \\ mov lr, #0
280 \\ mov fp, #0280 \\ str sp, %[argc_argv_ptr]
281 \\ mov lr, #0281 \\ and sp, #-16
282 \\ str sp, %[argc_argv_ptr]282 \\ b %[posixCallMainAndExit]
283 \\ and sp, #-16283 ,
284 \\ b %[posixCallMainAndExit]284 .riscv64 =>
285 ,285 \\ li s0, 0
286 else => @compileError("unsupported arch"),286 \\ li ra, 0
287 }287 \\ sd sp, %[argc_argv_ptr]
288 : [argc_argv_ptr] "=m" (argc_argv_ptr),288 \\ andi sp, sp, -16
289 : [posixCallMainAndExit] "X" (&posixCallMainAndExit),289 \\ tail %[posixCallMainAndExit]@plt
290 );290 ,
291 unreachable;291 .mips, .mipsel =>
292 },292 // The lr is already zeroed on entry, as specified by the ABI.
293 else => switch (native_arch) {293 \\ addiu $fp, $zero, 0
294 .x86_64 => {294 \\ sw $sp, %[argc_argv_ptr]
295 argc_argv_ptr = asm volatile (295 \\ .set push
296 \\ xor %%ebp, %%ebp296 \\ .set noat
297 : [argc] "={rsp}" (-> [*]usize),297 \\ addiu $1, $zero, -16
298 );298 \\ and $sp, $sp, $1
299 },299 \\ .set pop
300 .x86 => {300 \\ j %[posixCallMainAndExit]
301 argc_argv_ptr = asm volatile (301 ,
302 \\ xor %%ebp, %%ebp302 .mips64, .mips64el =>
303 : [argc] "={esp}" (-> [*]usize),303 // The lr is already zeroed on entry, as specified by the ABI.
304 );304 \\ addiu $fp, $zero, 0
305 },305 \\ sd $sp, %[argc_argv_ptr]
306 .aarch64, .aarch64_be, .arm, .armeb, .thumb => {306 \\ .set push
307 argc_argv_ptr = asm volatile (307 \\ .set noat
308 \\ mov fp, #0308 \\ daddiu $1, $zero, -16
309 \\ mov lr, #0309 \\ and $sp, $sp, $1
310 : [argc] "={sp}" (-> [*]usize),310 \\ .set pop
311 );311 \\ j %[posixCallMainAndExit]
312 },312 ,
313 .riscv64 => {313 .powerpc, .powerpcle =>
314 argc_argv_ptr = asm volatile (314 // Setup the initial stack frame and clear the back chain pointer.
315 \\ li s0, 0315 \\ stw 1, %[argc_argv_ptr]
316 \\ li ra, 0316 \\ li 0, 0
317 : [argc] "={sp}" (-> [*]usize),317 \\ stwu 1, -16(1)
318 );318 \\ stw 0, 0(1)
319 },319 \\ mtlr 0
320 .mips, .mipsel, .mips64, .mips64el => {320 \\ b %[posixCallMainAndExit]
321 // The lr is already zeroed on entry, as specified by the ABI.321 ,
322 argc_argv_ptr = asm volatile (322 .powerpc64, .powerpc64le =>
323 \\ move $fp, $0323 // Setup the initial stack frame and clear the back chain pointer.
324 : [argc] "={sp}" (-> [*]usize),324 // TODO: Support powerpc64 (big endian) on ELFv2.
325 );325 \\ std 1, %[argc_argv_ptr]
326 },326 \\ li 0, 0
327 .powerpc => {327 \\ stdu 0, -32(1)
328 // Setup the initial stack frame and clear the back chain pointer.328 \\ mtlr 0
329 argc_argv_ptr = asm volatile (329 \\ b %[posixCallMainAndExit]
330 \\ mr 4, 1330 ,
331 \\ li 0, 0331 .sparc64 =>
332 \\ stwu 1,-16(1)332 // argc is stored after a register window (16 registers) plus stack bias
333 \\ stw 0, 0(1)333 \\ mov %%g0, %%i6
334 \\ mtlr 0334 \\ add %%o6, 2175, %%l0
335 : [argc] "={r4}" (-> [*]usize),335 \\ stx %%l0, %[argc_argv_ptr]
336 :336 \\ ba %[posixCallMainAndExit]
337 : "r0"337 ,
338 );
339 },
340 .powerpc64le => {
341 // Setup the initial stack frame and clear the back chain pointer.
342 // TODO: Support powerpc64 (big endian) on ELFv2.
343 argc_argv_ptr = asm volatile (
344 \\ mr 4, 1
345 \\ li 0, 0
346 \\ stdu 0, -32(1)
347 \\ mtlr 0
348 : [argc] "={r4}" (-> [*]usize),
349 :
350 : "r0"
351 );
352 },
353 .sparc64 => {
354 // argc is stored after a register window (16 registers) plus stack bias
355 argc_argv_ptr = asm (
356 \\ mov %%g0, %%i6
357 \\ add %%o6, 2175, %[argc]
358 : [argc] "=r" (-> [*]usize),
359 );
360 },
361 else => @compileError("unsupported arch"),338 else => @compileError("unsupported arch"),
362 },339 }
363 }340 : [argc_argv_ptr] "=m" (argc_argv_ptr),
364 // If LLVM inlines stack variables into _start, they will overwrite341 : [posixCallMainAndExit] "X" (&posixCallMainAndExit),
365 // the command line argument data.342 );
366 @call(.never_inline, posixCallMainAndExit, .{});
367}343}
368344
369fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {345fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {
...@@ -390,8 +366,6 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {...@@ -390,8 +366,6 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
390}366}
391367
392fn posixCallMainAndExit() callconv(.C) noreturn {368fn posixCallMainAndExit() callconv(.C) noreturn {
393 @setAlignStack(16);
394
395 const argc = argc_argv_ptr[0];369 const argc = argc_argv_ptr[0];
396 const argv = @as([*][*:0]u8, @ptrCast(argc_argv_ptr + 1));370 const argv = @as([*][*:0]u8, @ptrCast(argc_argv_ptr + 1));
397371
lib/std/target.zig+5
...@@ -899,6 +899,10 @@ pub const Target = struct {...@@ -899,6 +899,10 @@ pub const Target = struct {
899 };899 };
900 }900 }
901901
902 pub fn isArmOrThumb(arch: Arch) bool {
903 return arch.isARM() or arch.isThumb();
904 }
905
902 pub fn isWasm(arch: Arch) bool {906 pub fn isWasm(arch: Arch) bool {
903 return switch (arch) {907 return switch (arch) {
904 .wasm32, .wasm64 => true,908 .wasm32, .wasm64 => true,
...@@ -1960,6 +1964,7 @@ pub const Target = struct {...@@ -1960,6 +1964,7 @@ pub const Target = struct {
1960 .thumbeb,1964 .thumbeb,
1961 => return if (target.os.tag.isDarwin() or target.os.tag == .windows) .signed else .unsigned,1965 => return if (target.os.tag.isDarwin() or target.os.tag == .windows) .signed else .unsigned,
1962 .powerpc, .powerpc64 => return if (target.os.tag.isDarwin()) .signed else .unsigned,1966 .powerpc, .powerpc64 => return if (target.os.tag.isDarwin()) .signed else .unsigned,
1967 .powerpcle,
1963 .powerpc64le,1968 .powerpc64le,
1964 .s390x,1969 .s390x,
1965 .xcore,1970 .xcore,
src/arch/x86_64/CodeGen.zig+155-54
...@@ -177,7 +177,7 @@ pub const MCValue = union(enum) {...@@ -177,7 +177,7 @@ pub const MCValue = union(enum) {
177 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.177 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.
178 register_overflow: struct { reg: Register, eflags: Condition },178 register_overflow: struct { reg: Register, eflags: Condition },
179 /// The value is in memory at a hard-coded address.179 /// The value is in memory at a hard-coded address.
180 /// If the type is a pointer, it means the pointer address is at this memory location.180 /// If the type is a pointer, it means the pointer address is stored at this memory location.
181 memory: u64,181 memory: u64,
182 /// The value is in memory at a constant offset from the address in a register.182 /// The value is in memory at a constant offset from the address in a register.
183 indirect: RegisterOffset,183 indirect: RegisterOffset,
...@@ -300,7 +300,7 @@ pub const MCValue = union(enum) {...@@ -300,7 +300,7 @@ pub const MCValue = union(enum) {
300 .load_tlv,300 .load_tlv,
301 .load_frame,301 .load_frame,
302 .reserved_frame,302 .reserved_frame,
303 => unreachable, // not a dereferenceable303 => unreachable, // not dereferenceable
304 .immediate => |addr| .{ .memory = addr },304 .immediate => |addr| .{ .memory = addr },
305 .register => |reg| .{ .indirect = .{ .reg = reg } },305 .register => |reg| .{ .indirect = .{ .reg = reg } },
306 .register_offset => |reg_off| .{ .indirect = reg_off },306 .register_offset => |reg_off| .{ .indirect = reg_off },
...@@ -3468,14 +3468,14 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa...@@ -3468,14 +3468,14 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
3468 const mod = self.bin_file.options.module.?;3468 const mod = self.bin_file.options.module.?;
3469 const abi_size: u32 = @intCast(ty.abiSize(mod));3469 const abi_size: u32 = @intCast(ty.abiSize(mod));
3470 const int_info = ty.intInfo(mod);3470 const int_info = ty.intInfo(mod);
3471 const dividend: Register = switch (lhs) {3471 const dividend = switch (lhs) {
3472 .register => |reg| reg,3472 .register => |reg| reg,
3473 else => try self.copyToTmpRegister(ty, lhs),3473 else => try self.copyToTmpRegister(ty, lhs),
3474 };3474 };
3475 const dividend_lock = self.register_manager.lockReg(dividend);3475 const dividend_lock = self.register_manager.lockReg(dividend);
3476 defer if (dividend_lock) |lock| self.register_manager.unlockReg(lock);3476 defer if (dividend_lock) |lock| self.register_manager.unlockReg(lock);
34773477
3478 const divisor: Register = switch (rhs) {3478 const divisor = switch (rhs) {
3479 .register => |reg| reg,3479 .register => |reg| reg,
3480 else => try self.copyToTmpRegister(ty, rhs),3480 else => try self.copyToTmpRegister(ty, rhs),
3481 };3481 };
...@@ -9184,6 +9184,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -9184,6 +9184,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
9184}9184}
91859185
9186fn airAsm(self: *Self, inst: Air.Inst.Index) !void {9186fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9187 const mod = self.bin_file.options.module.?;
9187 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;9188 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
9188 const extra = self.air.extraData(Air.Asm, ty_pl.payload);9189 const extra = self.air.extraData(Air.Asm, ty_pl.payload);
9189 const clobbers_len: u31 = @truncate(extra.data.flags);9190 const clobbers_len: u31 = @truncate(extra.data.flags);
...@@ -9196,23 +9197,15 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9196,23 +9197,15 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
91969197
9197 var result: MCValue = .none;9198 var result: MCValue = .none;
9198 var args = std.StringArrayHashMap(MCValue).init(self.gpa);9199 var args = std.StringArrayHashMap(MCValue).init(self.gpa);
9199 try args.ensureTotalCapacity(outputs.len + inputs.len + clobbers_len);9200 try args.ensureTotalCapacity(outputs.len + inputs.len);
9200 defer {9201 defer {
9201 for (args.values()) |arg| switch (arg) {9202 for (args.values()) |arg| if (arg.getReg()) |reg|
9202 .register => |reg| self.register_manager.unlockReg(.{ .register = reg }),9203 self.register_manager.unlockReg(.{ .register = reg });
9203 else => {},
9204 };
9205 args.deinit();9204 args.deinit();
9206 }9205 }
92079206
9208 if (outputs.len > 1) {9207 var outputs_extra_i = extra_i;
9209 return self.fail("TODO implement codegen for asm with more than 1 output", .{});
9210 }
9211
9212 for (outputs) |output| {9208 for (outputs) |output| {
9213 if (output != .none) {
9214 return self.fail("TODO implement codegen for non-expr asm", .{});
9215 }
9216 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);9209 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
9217 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);9210 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
9218 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);9211 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
...@@ -9220,21 +9213,48 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9220,21 +9213,48 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9220 // for the string, we still use the next u32 for the null terminator.9213 // for the string, we still use the next u32 for the null terminator.
9221 extra_i += (constraint.len + name.len + (2 + 3)) / 4;9214 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
92229215
9223 const mcv: MCValue = if (mem.eql(u8, constraint, "=r"))9216 const maybe_inst = switch (output) {
9224 .{ .register = self.register_manager.tryAllocReg(inst, gp) orelse9217 .none => inst,
9225 return self.fail("ran out of registers lowering inline asm", .{}) }9218 else => null,
9219 };
9220 const ty = switch (output) {
9221 .none => self.typeOfIndex(inst),
9222 else => self.typeOf(output).childType(mod),
9223 };
9224 const arg_maybe_reg: ?Register = if (mem.eql(u8, constraint, "=r"))
9225 self.register_manager.tryAllocReg(maybe_inst, regClassForType(ty, mod)) orelse
9226 return self.fail("ran out of registers lowering inline asm", .{})
9227 else if (mem.eql(u8, constraint, "=m"))
9228 if (output != .none) null else return self.fail(
9229 "memory constraint unsupported for asm result",
9230 .{},
9231 )
9232 else if (mem.eql(u8, constraint, "=g"))
9233 self.register_manager.tryAllocReg(maybe_inst, regClassForType(ty, mod)) orelse
9234 if (output != .none) null else return self.fail(
9235 "ran out of register lowering inline asm",
9236 .{},
9237 )
9226 else if (mem.startsWith(u8, constraint, "={") and mem.endsWith(u8, constraint, "}"))9238 else if (mem.startsWith(u8, constraint, "={") and mem.endsWith(u8, constraint, "}"))
9227 .{ .register = parseRegName(constraint["={".len .. constraint.len - "}".len]) orelse9239 parseRegName(constraint["={".len .. constraint.len - "}".len]) orelse
9228 return self.fail("unrecognized register constraint: '{s}'", .{constraint}) }9240 return self.fail("invalid register constraint: '{s}'", .{constraint})
9229 else9241 else
9230 return self.fail("unrecognized constraint: '{s}'", .{constraint});9242 return self.fail("invalid constraint: '{s}'", .{constraint});
9231 args.putAssumeCapacity(name, mcv);9243 const arg_mcv: MCValue = if (arg_maybe_reg) |reg| .{ .register = reg } else arg: {
9232 switch (mcv) {9244 const ptr_mcv = try self.resolveInst(output);
9233 .register => |reg| _ = if (RegisterManager.indexOfRegIntoTracked(reg)) |_|9245 switch (ptr_mcv) {
9234 self.register_manager.lockRegAssumeUnused(reg),9246 .immediate => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
9235 else => {},9247 break :arg ptr_mcv.deref(),
9236 }9248 .register, .register_offset, .lea_frame => break :arg ptr_mcv.deref(),
9237 if (output == .none) result = mcv;9249 else => {},
9250 }
9251 break :arg .{ .indirect = .{ .reg = try self.copyToTmpRegister(Type.usize, ptr_mcv) } };
9252 };
9253 if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {
9254 _ = self.register_manager.lockRegAssumeUnused(reg);
9255 };
9256 args.putAssumeCapacity(name, arg_mcv);
9257 if (output == .none) result = arg_mcv;
9238 }9258 }
92399259
9240 for (inputs) |input| {9260 for (inputs) |input| {
...@@ -9245,16 +9265,53 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9245,16 +9265,53 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9245 // for the string, we still use the next u32 for the null terminator.9265 // for the string, we still use the next u32 for the null terminator.
9246 extra_i += (constraint.len + name.len + (2 + 3)) / 4;9266 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
92479267
9248 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {9268 const ty = self.typeOf(input);
9249 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});9269 const input_mcv = try self.resolveInst(input);
9250 }9270 const arg_mcv: MCValue = if (mem.eql(u8, constraint, "r")) switch (input_mcv) {
9251 const reg_name = constraint[1 .. constraint.len - 1];9271 .register => input_mcv,
9252 const reg = parseRegName(reg_name) orelse9272 else => .{ .register = try self.copyToTmpRegister(ty, input_mcv) },
9253 return self.fail("unrecognized register: '{s}'", .{reg_name});9273 } else if (mem.eql(u8, constraint, "m")) arg: {
92549274 switch (input_mcv) {
9255 const arg_mcv = try self.resolveInst(input);9275 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
9256 try self.register_manager.getReg(reg, null);9276 break :arg input_mcv,
9257 try self.genSetReg(reg, self.typeOf(input), arg_mcv);9277 .indirect, .load_frame => break :arg input_mcv,
9278 .load_direct, .load_got, .load_tlv => {},
9279 else => {
9280 const temp_mcv = try self.allocTempRegOrMem(ty, false);
9281 try self.genCopy(ty, temp_mcv, input_mcv);
9282 break :arg temp_mcv;
9283 },
9284 }
9285 const addr_reg = self.register_manager.tryAllocReg(null, gp) orelse {
9286 const temp_mcv = try self.allocTempRegOrMem(ty, false);
9287 try self.genCopy(ty, temp_mcv, input_mcv);
9288 break :arg temp_mcv;
9289 };
9290 try self.genSetReg(addr_reg, Type.usize, input_mcv.address());
9291 break :arg .{ .indirect = .{ .reg = addr_reg } };
9292 } else if (mem.eql(u8, constraint, "g")) arg: {
9293 switch (input_mcv) {
9294 .register, .indirect, .load_frame => break :arg input_mcv,
9295 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
9296 break :arg input_mcv,
9297 else => {},
9298 }
9299 const temp_mcv = try self.allocTempRegOrMem(ty, true);
9300 try self.genCopy(ty, temp_mcv, input_mcv);
9301 break :arg temp_mcv;
9302 } else if (mem.eql(u8, constraint, "X"))
9303 input_mcv
9304 else if (mem.startsWith(u8, constraint, "{") and mem.endsWith(u8, constraint, "}")) arg: {
9305 const reg = parseRegName(constraint["{".len .. constraint.len - "}".len]) orelse
9306 return self.fail("invalid register constraint: '{s}'", .{constraint});
9307 try self.register_manager.getReg(reg, null);
9308 try self.genSetReg(reg, ty, input_mcv);
9309 break :arg .{ .register = reg };
9310 } else return self.fail("invalid constraint: '{s}'", .{constraint});
9311 if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {
9312 _ = self.register_manager.lockReg(reg);
9313 };
9314 args.putAssumeCapacity(name, arg_mcv);
9258 }9315 }
92599316
9260 {9317 {
...@@ -9293,7 +9350,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9293,7 +9350,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9293 }9350 }
9294 }9351 }
9295 break :mnem std.meta.stringToEnum(Mir.Inst.Tag, mnem_str) orelse9352 break :mnem std.meta.stringToEnum(Mir.Inst.Tag, mnem_str) orelse
9296 return self.fail("Invalid mnemonic: '{s}'", .{mnem_str});9353 return self.fail("invalid mnemonic: '{s}'", .{mnem_str});
9297 } };9354 } };
92989355
9299 var op_it = mem.tokenizeScalar(u8, mnem_it.rest(), ',');9356 var op_it = mem.tokenizeScalar(u8, mnem_it.rest(), ',');
...@@ -9304,43 +9361,73 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9304,43 +9361,73 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9304 if (mem.startsWith(u8, op_str, "%%")) {9361 if (mem.startsWith(u8, op_str, "%%")) {
9305 const colon = mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');9362 const colon = mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');
9306 const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse9363 const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse
9307 return self.fail("Invalid register: '{s}'", .{op_str});9364 return self.fail("invalid register: '{s}'", .{op_str});
9308 if (colon) |colon_pos| {9365 if (colon) |colon_pos| {
9309 const disp = std.fmt.parseInt(i32, op_str[colon_pos + 1 ..], 0) catch9366 const disp = std.fmt.parseInt(i32, op_str[colon_pos + 1 ..], 0) catch
9310 return self.fail("Invalid displacement: '{s}'", .{op_str});9367 return self.fail("invalid displacement: '{s}'", .{op_str});
9311 op.* = .{ .mem = Memory.sib(9368 op.* = .{ .mem = Memory.sib(
9312 mnem_size orelse return self.fail("Unknown size: '{s}'", .{op_str}),9369 mnem_size orelse return self.fail("unknown size: '{s}'", .{op_str}),
9313 .{ .base = .{ .reg = reg }, .disp = disp },9370 .{ .base = .{ .reg = reg }, .disp = disp },
9314 ) };9371 ) };
9315 } else {9372 } else {
9316 if (mnem_size) |size| if (reg.bitSize() != size.bitSize())9373 if (mnem_size) |size| if (reg.bitSize() != size.bitSize())
9317 return self.fail("Invalid register size: '{s}'", .{op_str});9374 return self.fail("invalid register size: '{s}'", .{op_str});
9318 op.* = .{ .reg = reg };9375 op.* = .{ .reg = reg };
9319 }9376 }
9320 } else if (mem.startsWith(u8, op_str, "%[") and mem.endsWith(u8, op_str, "]")) {9377 } else if (mem.startsWith(u8, op_str, "%[") and mem.endsWith(u8, op_str, "]")) {
9321 switch (args.get(op_str["%[".len .. op_str.len - "]".len]) orelse9378 const colon = mem.indexOfScalarPos(u8, op_str, "%[".len, ':');
9322 return self.fail("No matching constraint: '{s}'", .{op_str})) {9379 const modifier = if (colon) |colon_pos|
9323 .register => |reg| op.* = .{ .reg = reg },9380 op_str[colon_pos + 1 .. op_str.len - "]".len]
9324 else => return self.fail("Invalid constraint: '{s}'", .{op_str}),9381 else
9325 }9382 "";
9383 op.* = switch (args.get(op_str["%[".len .. colon orelse op_str.len - "]".len]) orelse
9384 return self.fail("no matching constraint: '{s}'", .{op_str})) {
9385 .register => |reg| if (std.mem.eql(u8, modifier, ""))
9386 .{ .reg = reg }
9387 else
9388 return self.fail("invalid modifier: '{s}'", .{modifier}),
9389 .memory => |addr| if (std.mem.eql(u8, modifier, "") or
9390 std.mem.eql(u8, modifier, "P"))
9391 .{ .mem = Memory.sib(
9392 mnem_size orelse return self.fail("unknown size: '{s}'", .{op_str}),
9393 .{ .base = .{ .reg = .ds }, .disp = @intCast(@as(i64, @bitCast(addr))) },
9394 ) }
9395 else
9396 return self.fail("invalid modifier: '{s}'", .{modifier}),
9397 .indirect => |reg_off| if (std.mem.eql(u8, modifier, ""))
9398 .{ .mem = Memory.sib(
9399 mnem_size orelse return self.fail("unknown size: '{s}'", .{op_str}),
9400 .{ .base = .{ .reg = reg_off.reg }, .disp = reg_off.off },
9401 ) }
9402 else
9403 return self.fail("invalid modifier: '{s}'", .{modifier}),
9404 .load_frame => |frame_addr| if (std.mem.eql(u8, modifier, ""))
9405 .{ .mem = Memory.sib(
9406 mnem_size orelse return self.fail("unknown size: '{s}'", .{op_str}),
9407 .{ .base = .{ .frame = frame_addr.index }, .disp = frame_addr.off },
9408 ) }
9409 else
9410 return self.fail("invalid modifier: '{s}'", .{modifier}),
9411 else => return self.fail("invalid constraint: '{s}'", .{op_str}),
9412 };
9326 } else if (mem.startsWith(u8, op_str, "$")) {9413 } else if (mem.startsWith(u8, op_str, "$")) {
9327 if (std.fmt.parseInt(i32, op_str["$".len..], 0)) |s| {9414 if (std.fmt.parseInt(i32, op_str["$".len..], 0)) |s| {
9328 if (mnem_size) |size| {9415 if (mnem_size) |size| {
9329 const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - (size.bitSize() - 1));9416 const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - (size.bitSize() - 1));
9330 if ((if (s < 0) ~s else s) > max)9417 if ((if (s < 0) ~s else s) > max)
9331 return self.fail("Invalid immediate size: '{s}'", .{op_str});9418 return self.fail("invalid immediate size: '{s}'", .{op_str});
9332 }9419 }
9333 op.* = .{ .imm = Immediate.s(s) };9420 op.* = .{ .imm = Immediate.s(s) };
9334 } else |_| if (std.fmt.parseInt(u64, op_str["$".len..], 0)) |u| {9421 } else |_| if (std.fmt.parseInt(u64, op_str["$".len..], 0)) |u| {
9335 if (mnem_size) |size| {9422 if (mnem_size) |size| {
9336 const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - size.bitSize());9423 const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - size.bitSize());
9337 if (u > max)9424 if (u > max)
9338 return self.fail("Invalid immediate size: '{s}'", .{op_str});9425 return self.fail("invalid immediate size: '{s}'", .{op_str});
9339 }9426 }
9340 op.* = .{ .imm = Immediate.u(u) };9427 op.* = .{ .imm = Immediate.u(u) };
9341 } else |_| return self.fail("Invalid immediate: '{s}'", .{op_str});9428 } else |_| return self.fail("invalid immediate: '{s}'", .{op_str});
9342 } else return self.fail("Invalid operand: '{s}'", .{op_str});9429 } else return self.fail("invalid operand: '{s}'", .{op_str});
9343 } else if (op_it.next()) |op_str| return self.fail("Extra operand: '{s}'", .{op_str});9430 } else if (op_it.next()) |op_str| return self.fail("extra operand: '{s}'", .{op_str});
93449431
9345 (switch (ops[0]) {9432 (switch (ops[0]) {
9346 .none => self.asmOpOnly(mnem_tag),9433 .none => self.asmOpOnly(mnem_tag),
...@@ -9407,6 +9494,20 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9407,6 +9494,20 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9407 };9494 };
9408 }9495 }
94099496
9497 for (outputs, args.values()[0..outputs.len]) |output, mcv| {
9498 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[outputs_extra_i..]);
9499 const constraint =
9500 std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[outputs_extra_i..]), 0);
9501 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
9502 // This equation accounts for the fact that even if we have exactly 4 bytes
9503 // for the string, we still use the next u32 for the null terminator.
9504 outputs_extra_i += (constraint.len + name.len + (2 + 3)) / 4;
9505
9506 if (output == .none) continue;
9507 if (mcv != .register) continue;
9508 try self.store(self.typeOf(output), try self.resolveInst(output), mcv);
9509 }
9510
9410 simple: {9511 simple: {
9411 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);9512 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);
9412 var buf_index: usize = 0;9513 var buf_index: usize = 0;
src/codegen/c.zig+2
...@@ -4770,9 +4770,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4770,9 +4770,11 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
4770}4770}
47714771
4772fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {4772fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {
4773 const target = f.object.dg.module.getTarget();
4773 return switch (constraint[0]) {4774 return switch (constraint[0]) {
4774 '{' => true,4775 '{' => true,
4775 'i', 'r' => false,4776 'i', 'r' => false,
4777 'I' => !target.cpu.arch.isArmOrThumb(),
4776 else => switch (value) {4778 else => switch (value) {
4777 .constant => |val| switch (f.object.dg.module.intern_pool.indexToKey(val)) {4779 .constant => |val| switch (f.object.dg.module.intern_pool.indexToKey(val)) {
4778 .ptr => |ptr| switch (ptr.addr) {4780 .ptr => |ptr| switch (ptr.addr) {
src/codegen/llvm.zig+9-7
...@@ -417,7 +417,7 @@ const DataLayoutBuilder = struct {...@@ -417,7 +417,7 @@ const DataLayoutBuilder = struct {
417 if (idx != size) try writer.print(":{d}", .{idx});417 if (idx != size) try writer.print(":{d}", .{idx});
418 }418 }
419 }419 }
420 if (self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb())420 if (self.target.cpu.arch.isArmOrThumb())
421 try writer.writeAll("-Fi8"); // for thumb interwork421 try writer.writeAll("-Fi8"); // for thumb interwork
422 if (self.target.cpu.arch != .hexagon) {422 if (self.target.cpu.arch != .hexagon) {
423 if (self.target.cpu.arch == .s390x) try self.typeAlignment(.integer, 1, 8, 8, false, writer);423 if (self.target.cpu.arch == .s390x) try self.typeAlignment(.integer, 1, 8, 8, false, writer);
...@@ -620,7 +620,7 @@ const DataLayoutBuilder = struct {...@@ -620,7 +620,7 @@ const DataLayoutBuilder = struct {
620 else => {},620 else => {},
621 }621 }
622 },622 },
623 .vector => if (self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb()) {623 .vector => if (self.target.cpu.arch.isArmOrThumb()) {
624 switch (size) {624 switch (size) {
625 128 => abi = 64,625 128 => abi = 64,
626 else => {},626 else => {},
...@@ -670,7 +670,7 @@ const DataLayoutBuilder = struct {...@@ -670,7 +670,7 @@ const DataLayoutBuilder = struct {
670 else => {},670 else => {},
671 },671 },
672 .aggregate => if (self.target.os.tag == .uefi or self.target.os.tag == .windows or672 .aggregate => if (self.target.os.tag == .uefi or self.target.os.tag == .windows or
673 self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb())673 self.target.cpu.arch.isArmOrThumb())
674 {674 {
675 pref = @min(pref, self.target.ptrBitWidth());675 pref = @min(pref, self.target.ptrBitWidth());
676 } else if (self.target.cpu.arch == .hexagon) {676 } else if (self.target.cpu.arch == .hexagon) {
...@@ -6809,8 +6809,6 @@ pub const FuncGen = struct {...@@ -6809,8 +6809,6 @@ pub const FuncGen = struct {
6809 }6809 }
6810 llvm_constraints.appendAssumeCapacity('=');6810 llvm_constraints.appendAssumeCapacity('=');
68116811
6812 // Pass any non-return outputs indirectly, if the constraint accepts a memory location
6813 is_indirect.* = (output != .none) and constraintAllowsMemory(constraint);
6814 if (output != .none) {6812 if (output != .none) {
6815 const output_inst = try self.resolveInst(output);6813 const output_inst = try self.resolveInst(output);
6816 const output_ty = self.typeOf(output);6814 const output_ty = self.typeOf(output);
...@@ -6825,6 +6823,8 @@ pub const FuncGen = struct {...@@ -6825,6 +6823,8 @@ pub const FuncGen = struct {
6825 }),6823 }),
6826 }6824 }
68276825
6826 // Pass any non-return outputs indirectly, if the constraint accepts a memory location
6827 is_indirect.* = constraintAllowsMemory(constraint);
6828 if (is_indirect.*) {6828 if (is_indirect.*) {
6829 // Pass the result by reference as an indirect output (e.g. "=*m")6829 // Pass the result by reference as an indirect output (e.g. "=*m")
6830 llvm_constraints.appendAssumeCapacity('*');6830 llvm_constraints.appendAssumeCapacity('*');
...@@ -6841,11 +6841,13 @@ pub const FuncGen = struct {...@@ -6841,11 +6841,13 @@ pub const FuncGen = struct {
6841 } else {6841 } else {
6842 switch (constraint[0]) {6842 switch (constraint[0]) {
6843 '=' => {},6843 '=' => {},
6844 else => return self.todo("unsupported output constraint on result type '{c}'", .{6844 else => return self.todo("unsupported output constraint on result type '{s}'", .{
6845 constraint[0],6845 constraint,
6846 }),6846 }),
6847 }6847 }
68486848
6849 is_indirect.* = false;
6850
6849 const ret_ty = self.typeOfIndex(inst);6851 const ret_ty = self.typeOfIndex(inst);
6850 llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty);6852 llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty);
6851 llvm_ret_i += 1;6853 llvm_ret_i += 1;
src/link/Elf.zig+1-1
...@@ -1654,7 +1654,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -1654,7 +1654,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
1654 }1654 }
16551655
1656 if (self.base.options.link_mode == .Static) {1656 if (self.base.options.link_mode == .Static) {
1657 if (target.cpu.arch.isARM() or target.cpu.arch.isThumb()) {1657 if (target.cpu.arch.isArmOrThumb()) {
1658 try argv.append("-Bstatic");1658 try argv.append("-Bstatic");
1659 } else {1659 } else {
1660 try argv.append("-static");1660 try argv.append("-static");
test/behavior/bitcast.zig+1-1
...@@ -421,7 +421,7 @@ test "bitcast nan float does modify signaling bit" {...@@ -421,7 +421,7 @@ test "bitcast nan float does modify signaling bit" {
421 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO421 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
422 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;422 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
423 // TODO: https://github.com/ziglang/zig/issues/14366423 // TODO: https://github.com/ziglang/zig/issues/14366
424 if (builtin.cpu.arch == .arm and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;424 if (builtin.zig_backend == .stage2_llvm and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
425425
426 // 16 bit426 // 16 bit
427 const snan_f16_const = math.nan_f16;427 const snan_f16_const = math.nan_f16;
test/behavior/call_tail.zig+10-1
...@@ -32,7 +32,16 @@ noinline fn insertionSort(data: []u64) void {...@@ -32,7 +32,16 @@ noinline fn insertionSort(data: []u64) void {
3232
33test "arguments pointed to on stack into tailcall" {33test "arguments pointed to on stack into tailcall" {
34 switch (builtin.cpu.arch) {34 switch (builtin.cpu.arch) {
35 .wasm32, .mips, .mipsel, .powerpc, .powerpcle, .powerpc64le => return error.SkipZigTest,35 .wasm32,
36 .mips,
37 .mipsel,
38 .mips64,
39 .mips64el,
40 .powerpc,
41 .powerpcle,
42 .powerpc64,
43 .powerpc64le,
44 => return error.SkipZigTest,
36 else => {},45 else => {},
37 }46 }
38 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;47 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
test/behavior/cast.zig+2-2
...@@ -123,7 +123,7 @@ test "@floatFromInt(f80)" {...@@ -123,7 +123,7 @@ test "@floatFromInt(f80)" {
123 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO123 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
124 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO124 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
125 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;125 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
126 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;126 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
127127
128 const S = struct {128 const S = struct {
129 fn doTheTest(comptime Int: type) !void {129 fn doTheTest(comptime Int: type) !void {
...@@ -1370,7 +1370,7 @@ test "cast f16 to wider types" {...@@ -1370,7 +1370,7 @@ test "cast f16 to wider types" {
1370 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1370 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1371 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1371 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1372 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1372 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1373 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;1373 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
13741374
1375 const S = struct {1375 const S = struct {
1376 fn doTheTest() !void {1376 fn doTheTest() !void {
test/behavior/eval.zig+1-1
...@@ -533,7 +533,7 @@ test "runtime 128 bit integer division" {...@@ -533,7 +533,7 @@ test "runtime 128 bit integer division" {
533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
534 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO534 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
535 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;535 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
536 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;536 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
537537
538 var a: u128 = 152313999999999991610955792383;538 var a: u128 = 152313999999999991610955792383;
539 var b: u128 = 10000000000000000000;539 var b: u128 = 10000000000000000000;
test/behavior/floatop.zig+9-9
...@@ -554,7 +554,7 @@ test "another, possibly redundant, @fabs test" {...@@ -554,7 +554,7 @@ test "another, possibly redundant, @fabs test" {
554 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO554 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
555 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO555 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
556 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;556 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
557 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;557 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
558558
559 try testFabsLegacy(f128, 12.0);559 try testFabsLegacy(f128, 12.0);
560 try comptime testFabsLegacy(f128, 12.0);560 try comptime testFabsLegacy(f128, 12.0);
...@@ -577,7 +577,7 @@ test "@fabs f80" {...@@ -577,7 +577,7 @@ test "@fabs f80" {
577 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO577 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
578 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO578 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
579 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;579 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
580 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;580 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
581581
582 try testFabsLegacy(f80, 12.0);582 try testFabsLegacy(f80, 12.0);
583 try comptime testFabsLegacy(f80, 12.0);583 try comptime testFabsLegacy(f80, 12.0);
...@@ -595,7 +595,7 @@ test "a third @fabs test, surely there should not be three fabs tests" {...@@ -595,7 +595,7 @@ test "a third @fabs test, surely there should not be three fabs tests" {
595 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO595 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
596 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO596 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
597 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;597 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
598 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;598 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
599599
600 inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {600 inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {
601 // normals601 // normals
...@@ -687,7 +687,7 @@ test "@floor f80" {...@@ -687,7 +687,7 @@ test "@floor f80" {
687 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO687 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
688 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO688 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
689 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;689 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
690 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;690 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
691691
692 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {692 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
693 // https://github.com/ziglang/zig/issues/12602693 // https://github.com/ziglang/zig/issues/12602
...@@ -704,7 +704,7 @@ test "@floor f128" {...@@ -704,7 +704,7 @@ test "@floor f128" {
704 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO704 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
705 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO705 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
706 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;706 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
707 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;707 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
708708
709 try testFloorLegacy(f128, 12.0);709 try testFloorLegacy(f128, 12.0);
710 try comptime testFloorLegacy(f128, 12.0);710 try comptime testFloorLegacy(f128, 12.0);
...@@ -785,7 +785,7 @@ test "@ceil f80" {...@@ -785,7 +785,7 @@ test "@ceil f80" {
785 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO785 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
786 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO786 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
787 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;787 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
788 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;788 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
789789
790 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {790 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
791 // https://github.com/ziglang/zig/issues/12602791 // https://github.com/ziglang/zig/issues/12602
...@@ -802,7 +802,7 @@ test "@ceil f128" {...@@ -802,7 +802,7 @@ test "@ceil f128" {
802 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO802 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
803 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO803 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
804 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;804 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
805 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;805 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
806806
807 try testCeilLegacy(f128, 12.0);807 try testCeilLegacy(f128, 12.0);
808 try comptime testCeilLegacy(f128, 12.0);808 try comptime testCeilLegacy(f128, 12.0);
...@@ -882,7 +882,7 @@ test "@trunc f80" {...@@ -882,7 +882,7 @@ test "@trunc f80" {
882 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO882 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
883 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO883 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
884 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;884 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
885 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;885 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
886886
887 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {887 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
888 // https://github.com/ziglang/zig/issues/12602888 // https://github.com/ziglang/zig/issues/12602
...@@ -905,7 +905,7 @@ test "@trunc f128" {...@@ -905,7 +905,7 @@ test "@trunc f128" {
905 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO905 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
906 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO906 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
907 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;907 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
908 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;908 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
909909
910 try testTruncLegacy(f128, 12.0);910 try testTruncLegacy(f128, 12.0);
911 try comptime testTruncLegacy(f128, 12.0);911 try comptime testTruncLegacy(f128, 12.0);
test/behavior/math.zig+4-4
...@@ -664,7 +664,7 @@ test "128-bit multiplication" {...@@ -664,7 +664,7 @@ test "128-bit multiplication" {
664 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO664 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
665 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO665 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
666 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;666 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
667 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;667 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
668668
669 {669 {
670 var a: i128 = 3;670 var a: i128 = 3;
...@@ -1312,7 +1312,7 @@ test "remainder division" {...@@ -1312,7 +1312,7 @@ test "remainder division" {
1312 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1312 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1313 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1313 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1314 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1314 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1315 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;1315 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
13161316
1317 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {1317 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1318 // https://github.com/ziglang/zig/issues/126021318 // https://github.com/ziglang/zig/issues/12602
...@@ -1457,7 +1457,7 @@ test "@round f80" {...@@ -1457,7 +1457,7 @@ test "@round f80" {
1457 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1457 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1458 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1458 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1459 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1459 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1460 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;1460 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
14611461
1462 try testRound(f80, 12.0);1462 try testRound(f80, 12.0);
1463 try comptime testRound(f80, 12.0);1463 try comptime testRound(f80, 12.0);
...@@ -1470,7 +1470,7 @@ test "@round f128" {...@@ -1470,7 +1470,7 @@ test "@round f128" {
1470 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1470 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1471 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1471 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1472 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1472 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1473 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;1473 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
14741474
1475 try testRound(f128, 12.0);1475 try testRound(f128, 12.0);
1476 try comptime testRound(f128, 12.0);1476 try comptime testRound(f128, 12.0);
test/behavior/maximum_minimum.zig+1-1
...@@ -110,7 +110,7 @@ test "@min/max for floats" {...@@ -110,7 +110,7 @@ test "@min/max for floats" {
110 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO110 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
111 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO111 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
112 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;112 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
113 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;113 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
114114
115 const S = struct {115 const S = struct {
116 fn doTheTest(comptime T: type) !void {116 fn doTheTest(comptime T: type) !void {
test/behavior/muladd.zig+4-4
...@@ -56,7 +56,7 @@ test "@mulAdd f80" {...@@ -56,7 +56,7 @@ test "@mulAdd f80" {
56 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO56 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO57 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;58 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
59 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;59 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
6060
61 try comptime testMulAdd80();61 try comptime testMulAdd80();
62 try testMulAdd80();62 try testMulAdd80();
...@@ -76,7 +76,7 @@ test "@mulAdd f128" {...@@ -76,7 +76,7 @@ test "@mulAdd f128" {
76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
78 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;78 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
79 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;79 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
8080
81 try comptime testMulAdd128();81 try comptime testMulAdd128();
82 try testMulAdd128();82 try testMulAdd128();
...@@ -179,7 +179,7 @@ test "vector f80" {...@@ -179,7 +179,7 @@ test "vector f80" {
179 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO179 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
180 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO180 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
181 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;181 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
182 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;182 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
183183
184 try comptime vector80();184 try comptime vector80();
185 try vector80();185 try vector80();
...@@ -204,7 +204,7 @@ test "vector f128" {...@@ -204,7 +204,7 @@ test "vector f128" {
204 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO204 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
206 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;206 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
207 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;207 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
208208
209 try comptime vector128();209 try comptime vector128();
210 try vector128();210 try vector128();
test/behavior/saturating_arithmetic.zig+1-1
...@@ -157,7 +157,7 @@ test "saturating multiplication" {...@@ -157,7 +157,7 @@ test "saturating multiplication" {
157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
159 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;159 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
160 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;160 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
161161
162 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .wasm32) {162 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .wasm32) {
163 // https://github.com/ziglang/zig/issues/9660163 // https://github.com/ziglang/zig/issues/9660
test/behavior/struct.zig+3-3
...@@ -428,7 +428,7 @@ test "packed struct 24bits" {...@@ -428,7 +428,7 @@ test "packed struct 24bits" {
428 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO428 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
429 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO429 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
430 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO430 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO
431 if (builtin.cpu.arch == .arm) return error.SkipZigTest; // TODO431 if (comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; // TODO
432 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO432 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
433 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;433 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
434434
...@@ -824,7 +824,7 @@ test "non-packed struct with u128 entry in union" {...@@ -824,7 +824,7 @@ test "non-packed struct with u128 entry in union" {
824 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO824 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
825 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO825 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
826 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;826 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
827 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;827 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
828828
829 const U = union(enum) {829 const U = union(enum) {
830 Num: u128,830 Num: u128,
...@@ -945,7 +945,7 @@ test "comptime struct field" {...@@ -945,7 +945,7 @@ test "comptime struct field" {
945 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;945 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
946946
947 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO947 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
948 if (builtin.cpu.arch == .arm) return error.SkipZigTest; // TODO948 if (comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; // TODO
949949
950 const T = struct {950 const T = struct {
951 a: i32,951 a: i32,
test/behavior/var_args.zig+4-4
...@@ -101,7 +101,7 @@ test "simple variadic function" {...@@ -101,7 +101,7 @@ test "simple variadic function" {
101 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO101 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
103 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;103 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
104 if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos) {104 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {
105 // https://github.com/ziglang/zig/issues/14096105 // https://github.com/ziglang/zig/issues/14096
106 return error.SkipZigTest;106 return error.SkipZigTest;
107 }107 }
...@@ -151,7 +151,7 @@ test "variadic functions" {...@@ -151,7 +151,7 @@ test "variadic functions" {
151 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO151 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
152 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO152 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
153 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;153 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
154 if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos) {154 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {
155 // https://github.com/ziglang/zig/issues/14096155 // https://github.com/ziglang/zig/issues/14096
156 return error.SkipZigTest;156 return error.SkipZigTest;
157 }157 }
...@@ -195,7 +195,7 @@ test "copy VaList" {...@@ -195,7 +195,7 @@ test "copy VaList" {
195 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO195 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
196 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO196 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
197 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;197 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
198 if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos) {198 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {
199 // https://github.com/ziglang/zig/issues/14096199 // https://github.com/ziglang/zig/issues/14096
200 return error.SkipZigTest;200 return error.SkipZigTest;
201 }201 }
...@@ -228,7 +228,7 @@ test "unused VaList arg" {...@@ -228,7 +228,7 @@ test "unused VaList arg" {
228 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO228 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
229 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO229 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
230 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;230 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
231 if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos) {231 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {
232 // https://github.com/ziglang/zig/issues/14096232 // https://github.com/ziglang/zig/issues/14096
233 return error.SkipZigTest;233 return error.SkipZigTest;
234 }234 }
test/behavior/vector.zig+3-2
...@@ -102,7 +102,7 @@ test "vector float operators" {...@@ -102,7 +102,7 @@ test "vector float operators" {
102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
104 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;104 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
105 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;105 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
106106
107 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {107 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
108 const S = struct {108 const S = struct {
...@@ -495,6 +495,7 @@ test "vector division operators" {...@@ -495,6 +495,7 @@ test "vector division operators" {
495 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO495 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
496 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO496 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
497 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO497 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
498 if (builtin.zig_backend == .stage2_llvm and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
498 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO499 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
499 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;500 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
500501
...@@ -706,7 +707,7 @@ test "vector reduce operation" {...@@ -706,7 +707,7 @@ test "vector reduce operation" {
706 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO707 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
707 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO708 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
708 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;709 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
709 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .arm) return error.SkipZigTest;710 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
710711
711 const S = struct {712 const S = struct {
712 fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {713 fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {
test/src/Cases.zig+1-1
...@@ -1524,7 +1524,7 @@ fn runOneCase(...@@ -1524,7 +1524,7 @@ fn runOneCase(
1524 }1524 }
1525 } else switch (host.getExternalExecutor(target_info, .{ .link_libc = case.link_libc })) {1525 } else switch (host.getExternalExecutor(target_info, .{ .link_libc = case.link_libc })) {
1526 .native => {1526 .native => {
1527 if (case.backend == .stage2 and case.target.getCpuArch() == .arm) {1527 if (case.backend == .stage2 and case.target.getCpuArch().isArmOrThumb()) {
1528 // https://github.com/ziglang/zig/issues/136231528 // https://github.com/ziglang/zig/issues/13623
1529 continue :update; // Pass test.1529 continue :update; // Pass test.
1530 }1530 }