authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-07-31 15:34:32-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-07-31 15:34:32-07:00
loge84cda0ebf8886346d42db78e8f3eb8d0bf515bd
tree9e0ed316fd374bcc3f7a4f26ff70291a9d1ca9fb
parent8f5c333ebe6631629be3b88d797a03b1d677d439
parent228c956377e4f33e45fad7e0ba5d9eb5073803a5
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #16622 from jacobly0/cbe-asm-compat

CBE: fix regressions and get new targets passing behavior tests

43 files changed, 769 insertions(+), 515 deletions(-)

lib/c.zig+91-96
......@@ -200,72 +200,67 @@ fn clone() callconv(.Naked) void {
200200 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
201201 // eax, ebx, ecx, edx, esi, edi
202202 asm volatile (
203 \\ push %%ebp
204 \\ mov %%esp,%%ebp
205 \\ push %%ebx
206 \\ push %%esi
207 \\ push %%edi
203 \\ pushl %%ebp
204 \\ movl %%esp,%%ebp
205 \\ pushl %%ebx
206 \\ pushl %%esi
207 \\ pushl %%edi
208208 \\ // Setup the arguments
209 \\ mov 16(%%ebp),%%ebx
210 \\ mov 12(%%ebp),%%ecx
211 \\ and $-16,%%ecx
212 \\ sub $20,%%ecx
213 \\ mov 20(%%ebp),%%eax
214 \\ mov %%eax,4(%%ecx)
215 \\ mov 8(%%ebp),%%eax
216 \\ mov %%eax,0(%%ecx)
217 \\ mov 24(%%ebp),%%edx
218 \\ mov 28(%%ebp),%%esi
219 \\ mov 32(%%ebp),%%edi
220 \\ mov $120,%%eax
209 \\ movl 16(%%ebp),%%ebx
210 \\ movl 12(%%ebp),%%ecx
211 \\ andl $-16,%%ecx
212 \\ subl $20,%%ecx
213 \\ movl 20(%%ebp),%%eax
214 \\ movl %%eax,4(%%ecx)
215 \\ movl 8(%%ebp),%%eax
216 \\ movl %%eax,0(%%ecx)
217 \\ movl 24(%%ebp),%%edx
218 \\ movl 28(%%ebp),%%esi
219 \\ movl 32(%%ebp),%%edi
220 \\ movl $120,%%eax
221221 \\ int $128
222 \\ test %%eax,%%eax
222 \\ testl %%eax,%%eax
223223 \\ jnz 1f
224 \\ pop %%eax
225 \\ xor %%ebp,%%ebp
226 \\ call *%%eax
227 \\ mov %%eax,%%ebx
228 \\ xor %%eax,%%eax
229 \\ inc %%eax
224 \\ popl %%eax
225 \\ xorl %%ebp,%%ebp
226 \\ calll *%%eax
227 \\ movl %%eax,%%ebx
228 \\ movl $1,%%eax
230229 \\ int $128
231 \\ hlt
232230 \\1:
233 \\ pop %%edi
234 \\ pop %%esi
235 \\ pop %%ebx
236 \\ pop %%ebp
237 \\ ret
231 \\ popl %%edi
232 \\ popl %%esi
233 \\ popl %%ebx
234 \\ popl %%ebp
235 \\ retl
238236 );
239237 },
240238 .x86_64 => {
241239 asm volatile (
242 \\ xor %%eax,%%eax
243 \\ mov $56,%%al // SYS_clone
244 \\ mov %%rdi,%%r11
245 \\ mov %%rdx,%%rdi
246 \\ mov %%r8,%%rdx
247 \\ mov %%r9,%%r8
248 \\ mov 8(%%rsp),%%r10
249 \\ mov %%r11,%%r9
250 \\ and $-16,%%rsi
251 \\ sub $8,%%rsi
252 \\ mov %%rcx,(%%rsi)
240 \\ movl $56,%%eax // SYS_clone
241 \\ movq %%rdi,%%r11
242 \\ movq %%rdx,%%rdi
243 \\ movq %%r8,%%rdx
244 \\ movq %%r9,%%r8
245 \\ movq 8(%%rsp),%%r10
246 \\ movq %%r11,%%r9
247 \\ andq $-16,%%rsi
248 \\ subq $8,%%rsi
249 \\ movq %%rcx,(%%rsi)
253250 \\ syscall
254 \\ test %%eax,%%eax
251 \\ testq %%rax,%%rax
255252 \\ jnz 1f
256 \\ xor %%ebp,%%ebp
257 \\ pop %%rdi
258 \\ call *%%r9
259 \\ mov %%eax,%%edi
260 \\ xor %%eax,%%eax
261 \\ mov $60,%%al // SYS_exit
253 \\ xorl %%ebp,%%ebp
254 \\ popq %%rdi
255 \\ callq *%%r9
256 \\ movl %%eax,%%edi
257 \\ movl $60,%%eax // SYS_exit
262258 \\ syscall
263 \\ hlt
264259 \\1: ret
265260 \\
266261 );
267262 },
268 .aarch64 => {
263 .aarch64, .aarch64_be => {
269264 // __clone(func, stack, flags, arg, ptid, tls, ctid)
270265 // x0, x1, w2, x3, x4, x5, x6
271266
......@@ -400,69 +395,69 @@ fn clone() callconv(.Naked) void {
400395 \\ syscall
401396 );
402397 },
403 .powerpc => {
398 .powerpc, .powerpcle => {
404399 // __clone(func, stack, flags, arg, ptid, tls, ctid)
405400 // 3, 4, 5, 6, 7, 8, 9
406401
407402 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
408403 // 0 3, 4, 5, 6, 7
409404 asm volatile (
410 \\# store non-volatile regs r30, r31 on stack in order to put our
411 \\# start func and its arg there
412 \\stwu 30, -16(1)
413 \\stw 31, 4(1)
405 \\ # store non-volatile regs r30, r31 on stack in order to put our
406 \\ # start func and its arg there
407 \\ stwu 30, -16(1)
408 \\ stw 31, 4(1)
414409 \\
415 \\# save r3 (func) into r30, and r6(arg) into r31
416 \\mr 30, 3
417 \\mr 31, 6
410 \\ # save r3 (func) into r30, and r6(arg) into r31
411 \\ mr 30, 3
412 \\ mr 31, 6
418413 \\
419 \\# create initial stack frame for new thread
420 \\clrrwi 4, 4, 4
421 \\li 0, 0
422 \\stwu 0, -16(4)
414 \\ # create initial stack frame for new thread
415 \\ clrrwi 4, 4, 4
416 \\ li 0, 0
417 \\ stwu 0, -16(4)
423418 \\
424 \\#move c into first arg
425 \\mr 3, 5
426 \\#mr 4, 4
427 \\mr 5, 7
428 \\mr 6, 8
429 \\mr 7, 9
419 \\ #move c into first arg
420 \\ mr 3, 5
421 \\ #mr 4, 4
422 \\ mr 5, 7
423 \\ mr 6, 8
424 \\ mr 7, 9
430425 \\
431 \\# move syscall number into r0
432 \\li 0, 120
426 \\ # move syscall number into r0
427 \\ li 0, 120
433428 \\
434 \\sc
429 \\ sc
435430 \\
436 \\# check for syscall error
437 \\bns+ 1f # jump to label 1 if no summary overflow.
438 \\#else
439 \\neg 3, 3 #negate the result (errno)
440 \\1:
441 \\# compare sc result with 0
442 \\cmpwi cr7, 3, 0
431 \\ # check for syscall error
432 \\ bns+ 1f # jump to label 1 if no summary overflow.
433 \\ #else
434 \\ neg 3, 3 #negate the result (errno)
435 \\ 1:
436 \\ # compare sc result with 0
437 \\ cmpwi cr7, 3, 0
443438 \\
444 \\# if not 0, jump to end
445 \\bne cr7, 2f
439 \\ # if not 0, jump to end
440 \\ bne cr7, 2f
446441 \\
447 \\#else: we're the child
448 \\#call funcptr: move arg (d) into r3
449 \\mr 3, 31
450 \\#move r30 (funcptr) into CTR reg
451 \\mtctr 30
452 \\# call CTR reg
453 \\bctrl
454 \\# mov SYS_exit into r0 (the exit param is already in r3)
455 \\li 0, 1
456 \\sc
442 \\ #else: we're the child
443 \\ #call funcptr: move arg (d) into r3
444 \\ mr 3, 31
445 \\ #move r30 (funcptr) into CTR reg
446 \\ mtctr 30
447 \\ # call CTR reg
448 \\ bctrl
449 \\ # mov SYS_exit into r0 (the exit param is already in r3)
450 \\ li 0, 1
451 \\ sc
457452 \\
458 \\2:
453 \\ 2:
459454 \\
460 \\# restore stack
461 \\lwz 30, 0(1)
462 \\lwz 31, 4(1)
463 \\addi 1, 1, 16
455 \\ # restore stack
456 \\ lwz 30, 0(1)
457 \\ lwz 31, 4(1)
458 \\ addi 1, 1, 16
464459 \\
465 \\blr
460 \\ blr
466461 );
467462 },
468463 .powerpc64, .powerpc64le => {
lib/compiler_rt/arm.zig+1-1
......@@ -9,7 +9,7 @@ pub const panic = common.panic;
99
1010comptime {
1111 if (!builtin.is_test) {
12 if (arch.isARM() or arch.isThumb()) {
12 if (arch.isArmOrThumb()) {
1313 @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = common.linkage, .visibility = common.visibility });
1414 @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = common.linkage, .visibility = common.visibility });
1515 @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" {
268268 try test__clzsi2(0xFE000000, 0);
269269 try test__clzsi2(0xFF000000, 0);
270270 // arm and thumb1 assume input a != 0
271 if (!builtin.cpu.arch.isARM() and !builtin.cpu.arch.isThumb())
271 if (!builtin.cpu.arch.isArmOrThumb())
272272 try test__clzsi2(0x00000000, 32);
273273 try test__clzsi2(0x00000001, 31);
274274 try test__clzsi2(0x00000002, 30);
lib/std/Thread.zig+8-6
......@@ -1275,12 +1275,14 @@ const LinuxThreadImpl = struct {
12751275 .entry_number = os.linux.tls.tls_image.gdt_entry_number,
12761276 .base_addr = tls_ptr,
12771277 .limit = 0xfffff,
1278 .seg_32bit = 1,
1279 .contents = 0, // Data
1280 .read_exec_only = 0,
1281 .limit_in_pages = 1,
1282 .seg_not_present = 0,
1283 .useable = 1,
1278 .flags = .{
1279 .seg_32bit = 1,
1280 .contents = 0, // Data
1281 .read_exec_only = 0,
1282 .limit_in_pages = 1,
1283 .seg_not_present = 0,
1284 .useable = 1,
1285 },
12841286 };
12851287 }
12861288
lib/std/builtin.zig+1-1
......@@ -568,7 +568,7 @@ pub const VaListX86_64 = extern struct {
568568/// This data structure is used by the Zig language code generation and
569569/// therefore must be kept in sync with the compiler implementation.
570570pub const VaList = switch (builtin.cpu.arch) {
571 .aarch64 => switch (builtin.os.tag) {
571 .aarch64, .aarch64_be => switch (builtin.os.tag) {
572572 .windows => *u8,
573573 .ios, .macos, .tvos, .watchos => *u8,
574574 else => @compileError("disabled due to miscompilations"), // VaListAarch64,
lib/std/os/linux.zig+6-8
......@@ -35,13 +35,13 @@ const syscall_bits = switch (native_arch) {
3535const arch_bits = switch (native_arch) {
3636 .x86 => @import("linux/x86.zig"),
3737 .x86_64 => @import("linux/x86_64.zig"),
38 .aarch64 => @import("linux/arm64.zig"),
38 .aarch64, .aarch64_be => @import("linux/arm64.zig"),
3939 .arm, .thumb => @import("linux/arm-eabi.zig"),
4040 .riscv64 => @import("linux/riscv64.zig"),
4141 .sparc64 => @import("linux/sparc64.zig"),
4242 .mips, .mipsel => @import("linux/mips.zig"),
4343 .mips64, .mips64el => @import("linux/mips64.zig"),
44 .powerpc => @import("linux/powerpc.zig"),
44 .powerpc, .powerpcle => @import("linux/powerpc.zig"),
4545 .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"),
4646 else => struct {},
4747};
......@@ -98,13 +98,13 @@ pub const syscalls = @import("linux/syscalls.zig");
9898pub const SYS = switch (@import("builtin").cpu.arch) {
9999 .x86 => syscalls.X86,
100100 .x86_64 => syscalls.X64,
101 .aarch64 => syscalls.Arm64,
101 .aarch64, .aarch64_be => syscalls.Arm64,
102102 .arm, .thumb => syscalls.Arm,
103103 .riscv64 => syscalls.RiscV64,
104104 .sparc64 => syscalls.Sparc64,
105105 .mips, .mipsel => syscalls.Mips,
106106 .mips64, .mips64el => syscalls.Mips64,
107 .powerpc => syscalls.PowerPC,
107 .powerpc, .powerpcle => syscalls.PowerPC,
108108 .powerpc64, .powerpc64le => syscalls.PowerPC64,
109109 else => @compileError("The Zig Standard Library is missing syscall definitions for the target CPU architecture"),
110110};
......@@ -1176,14 +1176,12 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact
11761176 const mask_size = @sizeOf(@TypeOf(ksa.mask));
11771177
11781178 if (act) |new| {
1179 const restore_rt_ptr = &restore_rt;
1180 const restore_ptr = &restore;
1181 const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) restore_rt_ptr else restore_ptr;
1179 const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) &restore_rt else &restore;
11821180 ksa = k_sigaction{
11831181 .handler = new.handler.handler,
11841182 .flags = new.flags | SA.RESTORER,
11851183 .mask = undefined,
1186 .restorer = @as(k_sigaction_funcs.restorer, @ptrCast(restorer_fn)),
1184 .restorer = @ptrCast(restorer_fn),
11871185 };
11881186 @memcpy(@as([*]u8, @ptrCast(&ksa.mask))[0..mask_size], @as([*]const u8, @ptrCast(&new.mask)));
11891187 }
lib/std/os/linux/arm-eabi.zig+32-12
......@@ -103,20 +103,40 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;
103103/// This matches the libc clone function.
104104pub 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 {
107 return asm volatile ("svc #0"
108 :
109 : [number] "{r7}" (@intFromEnum(SYS.sigreturn)),
110 : "memory"
111 );
106pub fn restore() callconv(.Naked) noreturn {
107 switch (@import("builtin").zig_backend) {
108 .stage2_c => asm volatile (
109 \\ mov r7, %[number]
110 \\ svc #0
111 :
112 : [number] "I" (@intFromEnum(SYS.sigreturn)),
113 : "memory"
114 ),
115 else => asm volatile (
116 \\ svc #0
117 :
118 : [number] "{r7}" (@intFromEnum(SYS.sigreturn)),
119 : "memory"
120 ),
121 }
112122}
113123
114pub fn restore_rt() callconv(.Naked) void {
115 return asm volatile ("svc #0"
116 :
117 : [number] "{r7}" (@intFromEnum(SYS.rt_sigreturn)),
118 : "memory"
119 );
124pub fn restore_rt() callconv(.Naked) noreturn {
125 switch (@import("builtin").zig_backend) {
126 .stage2_c => asm volatile (
127 \\ mov r7, %[number]
128 \\ svc #0
129 :
130 : [number] "I" (@intFromEnum(SYS.rt_sigreturn)),
131 : "memory"
132 ),
133 else => asm volatile (
134 \\ svc #0
135 :
136 : [number] "{r7}" (@intFromEnum(SYS.rt_sigreturn)),
137 : "memory"
138 ),
139 }
120140}
121141
122142pub const MMAP2_UNIT = 4096;
lib/std/os/linux/arm64.zig+4-3
......@@ -105,16 +105,17 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *
105105
106106pub const restore = restore_rt;
107107
108pub fn restore_rt() callconv(.Naked) void {
108pub fn restore_rt() callconv(.Naked) noreturn {
109109 switch (@import("builtin").zig_backend) {
110 .stage2_c => return asm volatile (
110 .stage2_c => asm volatile (
111111 \\ mov x8, %[number]
112112 \\ svc #0
113113 :
114114 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
115115 : "memory", "cc"
116116 ),
117 else => return asm volatile ("svc #0"
117 else => asm volatile (
118 \\ svc #0
118119 :
119120 : [number] "{x8}" (@intFromEnum(SYS.rt_sigreturn)),
120121 : "memory", "cc"
lib/std/os/linux/mips.zig+6-4
......@@ -195,16 +195,18 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;
195195/// This matches the libc clone function.
196196pub 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 {
199 return asm volatile ("syscall"
198pub fn restore() callconv(.Naked) noreturn {
199 asm volatile (
200 \\ syscall
200201 :
201202 : [number] "{$2}" (@intFromEnum(SYS.sigreturn)),
202203 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"
203204 );
204205}
205206
206pub fn restore_rt() callconv(.Naked) void {
207 return asm volatile ("syscall"
207pub fn restore_rt() callconv(.Naked) noreturn {
208 asm volatile (
209 \\ syscall
208210 :
209211 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),
210212 : "$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;
180180/// This matches the libc clone function.
181181pub 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 {
184 return asm volatile ("syscall"
183pub fn restore() callconv(.Naked) noreturn {
184 asm volatile (
185 \\ syscall
185186 :
186187 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),
187188 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"
188189 );
189190}
190191
191pub fn restore_rt() callconv(.Naked) void {
192 return asm volatile ("syscall"
192pub fn restore_rt() callconv(.Naked) noreturn {
193 asm volatile (
194 \\ syscall
193195 :
194196 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),
195197 : "$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:
133133
134134pub const restore = restore_rt;
135135
136pub fn restore_rt() callconv(.Naked) void {
137 return asm volatile ("sc"
136pub fn restore_rt() callconv(.Naked) noreturn {
137 asm volatile (
138 \\ sc
138139 :
139140 : [number] "{r0}" (@intFromEnum(SYS.rt_sigreturn)),
140141 : "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:
133133
134134pub const restore = restore_rt;
135135
136pub fn restore_rt() callconv(.Naked) void {
137 return asm volatile ("sc"
136pub fn restore_rt() callconv(.Naked) noreturn {
137 asm volatile (
138 \\ sc
138139 :
139140 : [number] "{r0}" (@intFromEnum(SYS.rt_sigreturn)),
140141 : "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: *
101101
102102pub const restore = restore_rt;
103103
104pub fn restore_rt() callconv(.Naked) void {
105 return asm volatile ("ecall"
104pub fn restore_rt() callconv(.Naked) noreturn {
105 asm volatile (
106 \\ ecall
106107 :
107108 : [number] "{x17}" (@intFromEnum(SYS.rt_sigreturn)),
108109 : "memory"
lib/std/os/linux/thumb.zig+4-4
......@@ -141,8 +141,8 @@ pub fn syscall6(
141141 );
142142}
143143
144pub fn restore() callconv(.Naked) void {
145 return asm volatile (
144pub fn restore() callconv(.Naked) noreturn {
145 asm volatile (
146146 \\ mov r7, %[number]
147147 \\ svc #0
148148 :
......@@ -150,8 +150,8 @@ pub fn restore() callconv(.Naked) void {
150150 );
151151}
152152
153pub fn restore_rt() callconv(.Naked) void {
154 return asm volatile (
153pub fn restore_rt() callconv(.Naked) noreturn {
154 asm volatile (
155155 \\ mov r7, %[number]
156156 \\ svc #0
157157 :
lib/std/os/linux/tls.zig+11-9
......@@ -48,7 +48,7 @@ const TLSVariant = enum {
4848};
4949
5050const 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,
5252 .x86_64, .x86, .sparc64 => TLSVariant.VariantII,
5353 else => @compileError("undefined tls_variant for this architecture"),
5454};
......@@ -115,12 +115,14 @@ pub fn setThreadPointer(addr: usize) void {
115115 .entry_number = tls_image.gdt_entry_number,
116116 .base_addr = addr,
117117 .limit = 0xfffff,
118 .seg_32bit = 1,
119 .contents = 0, // Data
120 .read_exec_only = 0,
121 .limit_in_pages = 1,
122 .seg_not_present = 0,
123 .useable = 1,
118 .flags = .{
119 .seg_32bit = 1,
120 .contents = 0, // Data
121 .read_exec_only = 0,
122 .limit_in_pages = 1,
123 .seg_not_present = 0,
124 .useable = 1,
125 },
124126 };
125127 const rc = std.os.linux.syscall1(.set_thread_area, @intFromPtr(&user_desc));
126128 assert(rc == 0);
......@@ -138,7 +140,7 @@ pub fn setThreadPointer(addr: usize) void {
138140 const rc = std.os.linux.syscall2(.arch_prctl, std.os.linux.ARCH.SET_FS, addr);
139141 assert(rc == 0);
140142 },
141 .aarch64 => {
143 .aarch64, .aarch64_be => {
142144 asm volatile (
143145 \\ msr tpidr_el0, %[addr]
144146 :
......@@ -160,7 +162,7 @@ pub fn setThreadPointer(addr: usize) void {
160162 const rc = std.os.linux.syscall1(.set_thread_area, addr);
161163 assert(rc == 0);
162164 },
163 .powerpc => {
165 .powerpc, .powerpcle => {
164166 asm volatile (
165167 \\ mr 2, %[addr]
166168 :
lib/std/os/linux/x86.zig+57-57
......@@ -123,46 +123,40 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;
123123/// This matches the libc clone function.
124124pub 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 {
127127 switch (@import("builtin").zig_backend) {
128128 .stage2_c => asm volatile (
129129 \\ movl %[number], %%eax
130130 \\ int $0x80
131 \\ ret
132131 :
133132 : [number] "i" (@intFromEnum(SYS.sigreturn)),
134133 : "memory"
135134 ),
136135 else => asm volatile (
137136 \\ int $0x80
138 \\ ret
139137 :
140138 : [number] "{eax}" (@intFromEnum(SYS.sigreturn)),
141139 : "memory"
142140 ),
143141 }
144 unreachable;
145142}
146143
147pub fn restore_rt() callconv(.Naked) void {
144pub fn restore_rt() callconv(.Naked) noreturn {
148145 switch (@import("builtin").zig_backend) {
149146 .stage2_c => asm volatile (
150147 \\ movl %[number], %%eax
151148 \\ int $0x80
152 \\ ret
153149 :
154150 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
155151 : "memory"
156152 ),
157153 else => asm volatile (
158154 \\ int $0x80
159 \\ ret
160155 :
161156 : [number] "{eax}" (@intFromEnum(SYS.rt_sigreturn)),
162157 : "memory"
163158 ),
164159 }
165 unreachable;
166160}
167161
168162pub const O = struct {
......@@ -354,16 +348,19 @@ pub const ucontext_t = extern struct {
354348
355349pub const Elf_Symndx = u32;
356350
357pub const user_desc = packed struct {
351pub const user_desc = extern struct {
358352 entry_number: u32,
359353 base_addr: u32,
360354 limit: u32,
361 seg_32bit: u1,
362 contents: u2,
363 read_exec_only: u1,
364 limit_in_pages: u1,
365 seg_not_present: u1,
366 useable: u1,
355 flags: packed struct(u32) {
356 seg_32bit: u1,
357 contents: u2,
358 read_exec_only: u1,
359 limit_in_pages: u1,
360 seg_not_present: u1,
361 useable: u1,
362 _: u25 = undefined,
363 },
367364};
368365
369366/// socketcall() call numbers
......@@ -398,77 +395,80 @@ noinline fn getContextReturnAddress() usize {
398395 return @returnAddress();
399396}
400397
401pub fn getContextInternal() callconv(.Naked) void {
398pub fn getContextInternal() callconv(.Naked) usize {
402399 asm volatile (
403 \\ movl $0, (%[flags_offset])(%%edx)
404 \\ movl $0, (%[link_offset])(%%edx)
405 \\ movl %%edi, (%[edi_offset])(%%edx)
406 \\ movl %%esi, (%[esi_offset])(%%edx)
407 \\ movl %%ebp, (%[ebp_offset])(%%edx)
408 \\ movl %%ebx, (%[ebx_offset])(%%edx)
409 \\ movl %%edx, (%[edx_offset])(%%edx)
410 \\ movl %%ecx, (%[ecx_offset])(%%edx)
411 \\ movl %%eax, (%[eax_offset])(%%edx)
400 \\ movl $0, %[flags_offset:c](%%edx)
401 \\ movl $0, %[link_offset:c](%%edx)
402 \\ movl %%edi, %[edi_offset:c](%%edx)
403 \\ movl %%esi, %[esi_offset:c](%%edx)
404 \\ movl %%ebp, %[ebp_offset:c](%%edx)
405 \\ movl %%ebx, %[ebx_offset:c](%%edx)
406 \\ movl %%edx, %[edx_offset:c](%%edx)
407 \\ movl %%ecx, %[ecx_offset:c](%%edx)
408 \\ movl %%eax, %[eax_offset:c](%%edx)
412409 \\ movl (%%esp), %%ecx
413 \\ movl %%ecx, (%[eip_offset])(%%edx)
410 \\ movl %%ecx, %[eip_offset:c](%%edx)
414411 \\ leal 4(%%esp), %%ecx
415 \\ movl %%ecx, (%[esp_offset])(%%edx)
412 \\ movl %%ecx, %[esp_offset:c](%%edx)
416413 \\ xorl %%ecx, %%ecx
417414 \\ movw %%fs, %%cx
418 \\ movl %%ecx, (%[fs_offset])(%%edx)
419 \\ leal (%[regspace_offset])(%%edx), %%ecx
420 \\ movl %%ecx, (%[fpregs_offset])(%%edx)
415 \\ movl %%ecx, %[fs_offset:c](%%edx)
416 \\ leal %[regspace_offset:c](%%edx), %%ecx
417 \\ movl %%ecx, %[fpregs_offset:c](%%edx)
421418 \\ fnstenv (%%ecx)
422419 \\ fldenv (%%ecx)
423420 \\ pushl %%ebx
424421 \\ pushl %%esi
425422 \\ xorl %%ebx, %%ebx
426423 \\ movl %[sigaltstack], %%eax
427 \\ leal (%[stack_offset])(%%edx), %%ecx
424 \\ leal %[stack_offset:c](%%edx), %%ecx
428425 \\ int $0x80
429 \\ cmpl $0, %%eax
430 \\ jne return
426 \\ testl %%eax, %%eax
427 \\ jnz 0f
431428 \\ movl %[sigprocmask], %%eax
432429 \\ xorl %%ecx, %%ecx
433 \\ leal (%[sigmask_offset])(%%edx), %%edx
430 \\ leal %[sigmask_offset:c](%%edx), %%edx
434431 \\ movl %[sigset_size], %%esi
435432 \\ int $0x80
436 \\ return:
433 \\0:
437434 \\ popl %%esi
438435 \\ popl %%ebx
436 \\ retl
439437 :
440 : [flags_offset] "p" (@offsetOf(ucontext_t, "flags")),
441 [link_offset] "p" (@offsetOf(ucontext_t, "link")),
442 [edi_offset] "p" (comptime gpRegisterOffset(REG.EDI)),
443 [esi_offset] "p" (comptime gpRegisterOffset(REG.ESI)),
444 [ebp_offset] "p" (comptime gpRegisterOffset(REG.EBP)),
445 [esp_offset] "p" (comptime gpRegisterOffset(REG.ESP)),
446 [ebx_offset] "p" (comptime gpRegisterOffset(REG.EBX)),
447 [edx_offset] "p" (comptime gpRegisterOffset(REG.EDX)),
448 [ecx_offset] "p" (comptime gpRegisterOffset(REG.ECX)),
449 [eax_offset] "p" (comptime gpRegisterOffset(REG.EAX)),
450 [eip_offset] "p" (comptime gpRegisterOffset(REG.EIP)),
451 [fs_offset] "p" (comptime gpRegisterOffset(REG.FS)),
452 [fpregs_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")),
453 [regspace_offset] "p" (@offsetOf(ucontext_t, "regspace")),
438 : [flags_offset] "i" (@offsetOf(ucontext_t, "flags")),
439 [link_offset] "i" (@offsetOf(ucontext_t, "link")),
440 [edi_offset] "i" (comptime gpRegisterOffset(REG.EDI)),
441 [esi_offset] "i" (comptime gpRegisterOffset(REG.ESI)),
442 [ebp_offset] "i" (comptime gpRegisterOffset(REG.EBP)),
443 [esp_offset] "i" (comptime gpRegisterOffset(REG.ESP)),
444 [ebx_offset] "i" (comptime gpRegisterOffset(REG.EBX)),
445 [edx_offset] "i" (comptime gpRegisterOffset(REG.EDX)),
446 [ecx_offset] "i" (comptime gpRegisterOffset(REG.ECX)),
447 [eax_offset] "i" (comptime gpRegisterOffset(REG.EAX)),
448 [eip_offset] "i" (comptime gpRegisterOffset(REG.EIP)),
449 [fs_offset] "i" (comptime gpRegisterOffset(REG.FS)),
450 [fpregs_offset] "i" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")),
451 [regspace_offset] "i" (@offsetOf(ucontext_t, "regspace")),
454452 [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)),
455 [stack_offset] "p" (@offsetOf(ucontext_t, "stack")),
453 [stack_offset] "i" (@offsetOf(ucontext_t, "stack")),
456454 [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)),
457 [sigmask_offset] "p" (@offsetOf(ucontext_t, "sigmask")),
455 [sigmask_offset] "i" (@offsetOf(ucontext_t, "sigmask")),
458456 [sigset_size] "i" (linux.NSIG / 8),
459 : "memory", "eax", "ecx", "edx"
457 : "cc", "memory", "eax", "ecx", "edx"
460458 );
461459}
462460
463461pub inline fn getcontext(context: *ucontext_t) usize {
464462 // This method is used so that getContextInternal can control
465463 // its prologue in order to read ESP from a constant offset.
466 // The unused &getContextInternal input is required so the function is included in the binary.
464 // An aligned stack is not needed for getContextInternal.
465 var clobber_edx: usize = undefined;
467466 return asm volatile (
468 \\ call os.linux.x86.getContextInternal
469 : [ret] "={eax}" (-> usize),
470 : [context] "{edx}" (context),
467 \\ calll %[getContextInternal:P]
468 : [_] "={eax}" (-> usize),
469 [_] "={edx}" (clobber_edx),
470 : [_] "{edx}" (context),
471471 [getContextInternal] "X" (&getContextInternal),
472 : "memory", "ecx"
472 : "cc", "memory", "ecx"
473473 );
474474}
lib/std/os/linux/x86_64.zig+67-67
......@@ -107,25 +107,22 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:
107107
108108pub const restore = restore_rt;
109109
110pub fn restore_rt() callconv(.Naked) void {
110pub fn restore_rt() callconv(.Naked) noreturn {
111111 switch (@import("builtin").zig_backend) {
112112 .stage2_c => asm volatile (
113113 \\ movl %[number], %%eax
114114 \\ syscall
115 \\ retq
116115 :
117116 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
118117 : "rcx", "r11", "memory"
119118 ),
120119 else => asm volatile (
121120 \\ syscall
122 \\ retq
123121 :
124122 : [number] "{rax}" (@intFromEnum(SYS.rt_sigreturn)),
125123 : "rcx", "r11", "memory"
126124 ),
127125 }
128 unreachable;
129126}
130127
131128pub const mode_t = usize;
......@@ -400,92 +397,95 @@ fn gpRegisterOffset(comptime reg_index: comptime_int) usize {
400397 return @offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "gregs") + @sizeOf(usize) * reg_index;
401398}
402399
403fn getContextInternal() callconv(.Naked) void {
400fn getContextInternal() callconv(.Naked) usize {
404401 // TODO: Read GS/FS registers?
405402 asm volatile (
406 \\ movq $0, (%[flags_offset])(%%rdi)
407 \\ movq $0, (%[link_offset])(%%rdi)
408 \\ movq %%r8, (%[r8_offset])(%%rdi)
409 \\ movq %%r9, (%[r9_offset])(%%rdi)
410 \\ movq %%r10, (%[r10_offset])(%%rdi)
411 \\ movq %%r11, (%[r11_offset])(%%rdi)
412 \\ movq %%r12, (%[r12_offset])(%%rdi)
413 \\ movq %%r13, (%[r13_offset])(%%rdi)
414 \\ movq %%r14, (%[r14_offset])(%%rdi)
415 \\ movq %%r15, (%[r15_offset])(%%rdi)
416 \\ movq %%rdi, (%[rdi_offset])(%%rdi)
417 \\ movq %%rsi, (%[rsi_offset])(%%rdi)
418 \\ movq %%rbp, (%[rbp_offset])(%%rdi)
419 \\ movq %%rbx, (%[rbx_offset])(%%rdi)
420 \\ movq %%rdx, (%[rdx_offset])(%%rdi)
421 \\ movq %%rax, (%[rax_offset])(%%rdi)
422 \\ movq %%rcx, (%[rcx_offset])(%%rdi)
403 \\ movq $0, %[flags_offset:c](%%rdi)
404 \\ movq $0, %[link_offset:c](%%rdi)
405 \\ movq %%r8, %[r8_offset:c](%%rdi)
406 \\ movq %%r9, %[r9_offset:c](%%rdi)
407 \\ movq %%r10, %[r10_offset:c](%%rdi)
408 \\ movq %%r11, %[r11_offset:c](%%rdi)
409 \\ movq %%r12, %[r12_offset:c](%%rdi)
410 \\ movq %%r13, %[r13_offset:c](%%rdi)
411 \\ movq %%r14, %[r14_offset:c](%%rdi)
412 \\ movq %%r15, %[r15_offset:c](%%rdi)
413 \\ movq %%rdi, %[rdi_offset:c](%%rdi)
414 \\ movq %%rsi, %[rsi_offset:c](%%rdi)
415 \\ movq %%rbp, %[rbp_offset:c](%%rdi)
416 \\ movq %%rbx, %[rbx_offset:c](%%rdi)
417 \\ movq %%rdx, %[rdx_offset:c](%%rdi)
418 \\ movq %%rax, %[rax_offset:c](%%rdi)
419 \\ movq %%rcx, %[rcx_offset:c](%%rdi)
423420 \\ movq (%%rsp), %%rcx
424 \\ movq %%rcx, (%[rip_offset])(%%rdi)
421 \\ movq %%rcx, %[rip_offset:c](%%rdi)
425422 \\ leaq 8(%%rsp), %%rcx
426 \\ movq %%rcx, (%[rsp_offset])(%%rdi)
423 \\ movq %%rcx, %[rsp_offset:c](%%rdi)
427424 \\ pushfq
428 \\ popq (%[efl_offset])(%%rdi)
429 \\ leaq (%[fpmem_offset])(%%rdi), %%rcx
430 \\ movq %%rcx, (%[fpstate_offset])(%%rdi)
425 \\ popq %[efl_offset:c](%%rdi)
426 \\ leaq %[fpmem_offset:c](%%rdi), %%rcx
427 \\ movq %%rcx, %[fpstate_offset:c](%%rdi)
431428 \\ fnstenv (%%rcx)
432429 \\ fldenv (%%rcx)
433 \\ stmxcsr (%[mxcsr_offset])(%%rdi)
434 \\ leaq (%[stack_offset])(%%rdi), %%rsi
430 \\ stmxcsr %[mxcsr_offset:c](%%rdi)
431 \\ leaq %[stack_offset:c](%%rdi), %%rsi
435432 \\ movq %%rdi, %%r8
436 \\ xorq %%rdi, %%rdi
433 \\ xorl %%edi, %%edi
437434 \\ movq %[sigaltstack], %%rax
438435 \\ syscall
439 \\ cmpq $0, %%rax
440 \\ jne return
436 \\ testq %%rax, %%rax
437 \\ jnz 0f
441438 \\ movq %[sigprocmask], %%rax
442 \\ xorq %%rsi, %%rsi
443 \\ leaq (%[sigmask_offset])(%%r8), %%rdx
444 \\ movq %[sigset_size], %%r10
439 \\ xorl %%esi, %%esi
440 \\ leaq %[sigmask_offset:c](%%r8), %%rdx
441 \\ movl %[sigset_size], %%r10d
445442 \\ syscall
446 \\ return:
443 \\0:
444 \\ retq
447445 :
448 : [flags_offset] "p" (@offsetOf(ucontext_t, "flags")),
449 [link_offset] "p" (@offsetOf(ucontext_t, "link")),
450 [r8_offset] "p" (comptime gpRegisterOffset(REG.R8)),
451 [r9_offset] "p" (comptime gpRegisterOffset(REG.R9)),
452 [r10_offset] "p" (comptime gpRegisterOffset(REG.R10)),
453 [r11_offset] "p" (comptime gpRegisterOffset(REG.R11)),
454 [r12_offset] "p" (comptime gpRegisterOffset(REG.R12)),
455 [r13_offset] "p" (comptime gpRegisterOffset(REG.R13)),
456 [r14_offset] "p" (comptime gpRegisterOffset(REG.R14)),
457 [r15_offset] "p" (comptime gpRegisterOffset(REG.R15)),
458 [rdi_offset] "p" (comptime gpRegisterOffset(REG.RDI)),
459 [rsi_offset] "p" (comptime gpRegisterOffset(REG.RSI)),
460 [rbp_offset] "p" (comptime gpRegisterOffset(REG.RBP)),
461 [rbx_offset] "p" (comptime gpRegisterOffset(REG.RBX)),
462 [rdx_offset] "p" (comptime gpRegisterOffset(REG.RDX)),
463 [rax_offset] "p" (comptime gpRegisterOffset(REG.RAX)),
464 [rcx_offset] "p" (comptime gpRegisterOffset(REG.RCX)),
465 [rsp_offset] "p" (comptime gpRegisterOffset(REG.RSP)),
466 [rip_offset] "p" (comptime gpRegisterOffset(REG.RIP)),
467 [efl_offset] "p" (comptime gpRegisterOffset(REG.EFL)),
468 [fpstate_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")),
469 [fpmem_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem")),
470 [mxcsr_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem") + @offsetOf(fpstate, "mxcsr")),
446 : [flags_offset] "i" (@offsetOf(ucontext_t, "flags")),
447 [link_offset] "i" (@offsetOf(ucontext_t, "link")),
448 [r8_offset] "i" (comptime gpRegisterOffset(REG.R8)),
449 [r9_offset] "i" (comptime gpRegisterOffset(REG.R9)),
450 [r10_offset] "i" (comptime gpRegisterOffset(REG.R10)),
451 [r11_offset] "i" (comptime gpRegisterOffset(REG.R11)),
452 [r12_offset] "i" (comptime gpRegisterOffset(REG.R12)),
453 [r13_offset] "i" (comptime gpRegisterOffset(REG.R13)),
454 [r14_offset] "i" (comptime gpRegisterOffset(REG.R14)),
455 [r15_offset] "i" (comptime gpRegisterOffset(REG.R15)),
456 [rdi_offset] "i" (comptime gpRegisterOffset(REG.RDI)),
457 [rsi_offset] "i" (comptime gpRegisterOffset(REG.RSI)),
458 [rbp_offset] "i" (comptime gpRegisterOffset(REG.RBP)),
459 [rbx_offset] "i" (comptime gpRegisterOffset(REG.RBX)),
460 [rdx_offset] "i" (comptime gpRegisterOffset(REG.RDX)),
461 [rax_offset] "i" (comptime gpRegisterOffset(REG.RAX)),
462 [rcx_offset] "i" (comptime gpRegisterOffset(REG.RCX)),
463 [rsp_offset] "i" (comptime gpRegisterOffset(REG.RSP)),
464 [rip_offset] "i" (comptime gpRegisterOffset(REG.RIP)),
465 [efl_offset] "i" (comptime gpRegisterOffset(REG.EFL)),
466 [fpstate_offset] "i" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")),
467 [fpmem_offset] "i" (@offsetOf(ucontext_t, "fpregs_mem")),
468 [mxcsr_offset] "i" (@offsetOf(ucontext_t, "fpregs_mem") + @offsetOf(fpstate, "mxcsr")),
471469 [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)),
472 [stack_offset] "p" (@offsetOf(ucontext_t, "stack")),
470 [stack_offset] "i" (@offsetOf(ucontext_t, "stack")),
473471 [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)),
474 [sigmask_offset] "p" (@offsetOf(ucontext_t, "sigmask")),
472 [sigmask_offset] "i" (@offsetOf(ucontext_t, "sigmask")),
475473 [sigset_size] "i" (linux.NSIG / 8),
476 : "memory", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11"
474 : "cc", "memory", "rax", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11"
477475 );
478476}
479477
480478pub inline fn getcontext(context: *ucontext_t) usize {
481479 // This method is used so that getContextInternal can control
482480 // 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.
482 var clobber_rdi: usize = undefined;
484483 return asm volatile (
485 \\ call os.linux.x86_64.getContextInternal
486 : [ret] "={rax}" (-> usize),
487 : [context] "{rdi}" (context),
484 \\ callq %[getContextInternal:P]
485 : [_] "={rax}" (-> usize),
486 [_] "={rdi}" (clobber_rdi),
487 : [_] "{rdi}" (context),
488488 [getContextInternal] "X" (&getContextInternal),
489 : "memory", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11"
489 : "cc", "memory", "rcx", "rdx", "rsi", "r8", "r10", "r11"
490490 );
491491}
lib/std/start.zig+86-112
......@@ -101,7 +101,7 @@ fn main2() callconv(.C) c_int {
101101 return 0;
102102}
103103
104fn _start2() callconv(.Naked) noreturn {
104fn _start2() noreturn {
105105 callMain2();
106106}
107107
......@@ -254,116 +254,92 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv
254254}
255255
256256fn _start() callconv(.Naked) noreturn {
257 switch (builtin.zig_backend) {
258 .stage2_c => {
259 @export(argc_argv_ptr, .{ .name = "argc_argv_ptr" });
260 @export(posixCallMainAndExit, .{ .name = "_posixCallMainAndExit" });
261 switch (native_arch) {
262 .x86_64 => asm volatile (
263 \\ xorl %%ebp, %%ebp
264 \\ movq %%rsp, argc_argv_ptr
265 \\ andq $-16, %%rsp
266 \\ call _posixCallMainAndExit
267 ),
268 .x86 => asm volatile (
269 \\ xorl %%ebp, %%ebp
270 \\ movl %%esp, argc_argv_ptr
271 \\ andl $-16, %%esp
272 \\ jmp _posixCallMainAndExit
273 ),
274 .aarch64, .aarch64_be => asm volatile (
275 \\ mov fp, #0
276 \\ mov lr, #0
277 \\ mov x0, sp
278 \\ adrp x1, argc_argv_ptr
279 \\ str x0, [x1, :lo12:argc_argv_ptr]
280 \\ b _posixCallMainAndExit
281 ),
282 .arm, .armeb, .thumb => asm volatile (
283 \\ mov fp, #0
284 \\ mov lr, #0
285 \\ str sp, argc_argv_ptr
286 \\ and sp, #-16
287 \\ b _posixCallMainAndExit
288 ),
289 else => @compileError("unsupported arch"),
290 }
291 unreachable;
292 },
293 else => switch (native_arch) {
294 .x86_64 => {
295 argc_argv_ptr = asm volatile (
296 \\ xor %%ebp, %%ebp
297 : [argc] "={rsp}" (-> [*]usize),
298 );
299 },
300 .x86 => {
301 argc_argv_ptr = asm volatile (
302 \\ xor %%ebp, %%ebp
303 : [argc] "={esp}" (-> [*]usize),
304 );
305 },
306 .aarch64, .aarch64_be, .arm, .armeb, .thumb => {
307 argc_argv_ptr = asm volatile (
308 \\ mov fp, #0
309 \\ mov lr, #0
310 : [argc] "={sp}" (-> [*]usize),
311 );
312 },
313 .riscv64 => {
314 argc_argv_ptr = asm volatile (
315 \\ li s0, 0
316 \\ li ra, 0
317 : [argc] "={sp}" (-> [*]usize),
318 );
319 },
320 .mips, .mipsel, .mips64, .mips64el => {
321 // The lr is already zeroed on entry, as specified by the ABI.
322 argc_argv_ptr = asm volatile (
323 \\ move $fp, $0
324 : [argc] "={sp}" (-> [*]usize),
325 );
326 },
327 .powerpc => {
328 // Setup the initial stack frame and clear the back chain pointer.
329 argc_argv_ptr = asm volatile (
330 \\ mr 4, 1
331 \\ li 0, 0
332 \\ stwu 1,-16(1)
333 \\ stw 0, 0(1)
334 \\ mtlr 0
335 : [argc] "={r4}" (-> [*]usize),
336 :
337 : "r0"
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 },
257 asm volatile (switch (native_arch) {
258 .x86_64 =>
259 \\ xorl %%ebp, %%ebp
260 \\ movq %%rsp, %[argc_argv_ptr]
261 \\ andq $-16, %%rsp
262 \\ callq %[posixCallMainAndExit:P]
263 ,
264 .x86 =>
265 \\ xorl %%ebp, %%ebp
266 \\ movl %%esp, %[argc_argv_ptr]
267 \\ andl $-16, %%esp
268 \\ calll %[posixCallMainAndExit:P]
269 ,
270 .aarch64, .aarch64_be =>
271 \\ mov fp, #0
272 \\ mov lr, #0
273 \\ mov x0, sp
274 \\ str x0, %[argc_argv_ptr]
275 \\ b %[posixCallMainAndExit]
276 ,
277 .arm, .armeb, .thumb, .thumbeb =>
278 \\ mov fp, #0
279 \\ mov lr, #0
280 \\ str sp, %[argc_argv_ptr]
281 \\ and sp, #-16
282 \\ b %[posixCallMainAndExit]
283 ,
284 .riscv64 =>
285 \\ li s0, 0
286 \\ li ra, 0
287 \\ sd sp, %[argc_argv_ptr]
288 \\ andi sp, sp, -16
289 \\ tail %[posixCallMainAndExit]@plt
290 ,
291 .mips, .mipsel =>
292 // The lr is already zeroed on entry, as specified by the ABI.
293 \\ addiu $fp, $zero, 0
294 \\ sw $sp, %[argc_argv_ptr]
295 \\ .set push
296 \\ .set noat
297 \\ addiu $1, $zero, -16
298 \\ and $sp, $sp, $1
299 \\ .set pop
300 \\ j %[posixCallMainAndExit]
301 ,
302 .mips64, .mips64el =>
303 // The lr is already zeroed on entry, as specified by the ABI.
304 \\ addiu $fp, $zero, 0
305 \\ sd $sp, %[argc_argv_ptr]
306 \\ .set push
307 \\ .set noat
308 \\ daddiu $1, $zero, -16
309 \\ and $sp, $sp, $1
310 \\ .set pop
311 \\ j %[posixCallMainAndExit]
312 ,
313 .powerpc, .powerpcle =>
314 // Setup the initial stack frame and clear the back chain pointer.
315 \\ stw 1, %[argc_argv_ptr]
316 \\ li 0, 0
317 \\ stwu 1, -16(1)
318 \\ stw 0, 0(1)
319 \\ mtlr 0
320 \\ b %[posixCallMainAndExit]
321 ,
322 .powerpc64, .powerpc64le =>
323 // Setup the initial stack frame and clear the back chain pointer.
324 // TODO: Support powerpc64 (big endian) on ELFv2.
325 \\ std 1, %[argc_argv_ptr]
326 \\ li 0, 0
327 \\ stdu 0, -32(1)
328 \\ mtlr 0
329 \\ b %[posixCallMainAndExit]
330 ,
331 .sparc64 =>
332 // argc is stored after a register window (16 registers) plus stack bias
333 \\ mov %%g0, %%i6
334 \\ add %%o6, 2175, %%l0
335 \\ stx %%l0, %[argc_argv_ptr]
336 \\ ba %[posixCallMainAndExit]
337 ,
361338 else => @compileError("unsupported arch"),
362 },
363 }
364 // If LLVM inlines stack variables into _start, they will overwrite
365 // the command line argument data.
366 @call(.never_inline, posixCallMainAndExit, .{});
339 }
340 : [argc_argv_ptr] "=m" (argc_argv_ptr),
341 : [posixCallMainAndExit] "X" (&posixCallMainAndExit),
342 );
367343}
368344
369345fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {
......@@ -390,8 +366,6 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
390366}
391367
392368fn posixCallMainAndExit() callconv(.C) noreturn {
393 @setAlignStack(16);
394
395369 const argc = argc_argv_ptr[0];
396370 const argv = @as([*][*:0]u8, @ptrCast(argc_argv_ptr + 1));
397371
lib/std/target.zig+5
......@@ -899,6 +899,10 @@ pub const Target = struct {
899899 };
900900 }
901901
902 pub fn isArmOrThumb(arch: Arch) bool {
903 return arch.isARM() or arch.isThumb();
904 }
905
902906 pub fn isWasm(arch: Arch) bool {
903907 return switch (arch) {
904908 .wasm32, .wasm64 => true,
......@@ -1960,6 +1964,7 @@ pub const Target = struct {
19601964 .thumbeb,
19611965 => return if (target.os.tag.isDarwin() or target.os.tag == .windows) .signed else .unsigned,
19621966 .powerpc, .powerpc64 => return if (target.os.tag.isDarwin()) .signed else .unsigned,
1967 .powerpcle,
19631968 .powerpc64le,
19641969 .s390x,
19651970 .xcore,
lib/zig.h+76-13
......@@ -1176,10 +1176,10 @@ typedef signed __int128 zig_i128;
11761176
11771177#if zig_little_endian
11781178typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128;
1179typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128;
1179typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128;
11801180#else
11811181typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128;
1182typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
1182typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
11831183#endif
11841184
11851185#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
......@@ -3197,11 +3197,9 @@ zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64,
31973197zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2)
31983198zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2)
31993199zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2)
3200zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2)
32013200zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2)
32023201zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2)
32033202zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2)
3204zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2)
32053203zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2)
32063204zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2)
32073205zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2)
......@@ -3213,6 +3211,21 @@ zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32,
32133211zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2)
32143212zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2)
32153213
3214#ifdef __ARM_EABI__
3215
3216zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64);
3217static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); }
3218
3219zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32);
3220static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); }
3221
3222#else /* __ARM_EABI__ */
3223
3224zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2)
3225zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2)
3226
3227#endif /* __ARM_EABI__ */
3228
32163229#define zig_float_negate_builtin_0(w, c, sb) \
32173230 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb))
32183231#define zig_float_negate_builtin_1(w, c, sb) -arg
......@@ -3255,17 +3268,11 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
32553268 return lhs operator rhs; \
32563269 }
32573270
3258#define zig_float_builtins(w) \
3259 zig_convert_builtin( int32_t, int32_t, fix, zig_f##w, zig_f##w, ) \
3260 zig_convert_builtin(uint32_t, uint32_t, fixuns, zig_f##w, zig_f##w, ) \
3271#define zig_common_float_builtins(w) \
32613272 zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \
3262 zig_convert_builtin(uint64_t, uint64_t, fixuns, zig_f##w, zig_f##w, ) \
32633273 zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \
32643274 zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \
3265 zig_convert_builtin(zig_f##w, zig_f##w, float, int32_t, int32_t, ) \
3266 zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint32_t, uint32_t, ) \
32673275 zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \
3268 zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint64_t, uint64_t, ) \
32693276 zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \
32703277 zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \
32713278 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \
......@@ -3309,12 +3316,68 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
33093316 static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \
33103317 return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \
33113318 }
3319zig_common_float_builtins(16)
3320zig_common_float_builtins(32)
3321zig_common_float_builtins(64)
3322zig_common_float_builtins(80)
3323zig_common_float_builtins(128)
3324
3325#define zig_float_builtins(w) \
3326 zig_convert_builtin( int32_t, int32_t, fix, zig_f##w, zig_f##w, ) \
3327 zig_convert_builtin(uint32_t, uint32_t, fixuns, zig_f##w, zig_f##w, ) \
3328 zig_convert_builtin(uint64_t, uint64_t, fixuns, zig_f##w, zig_f##w, ) \
3329 zig_convert_builtin(zig_f##w, zig_f##w, float, int32_t, int32_t, ) \
3330 zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint32_t, uint32_t, ) \
3331 zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint64_t, uint64_t, )
33123332zig_float_builtins(16)
3313zig_float_builtins(32)
3314zig_float_builtins(64)
33153333zig_float_builtins(80)
33163334zig_float_builtins(128)
33173335
3336#ifdef __ARM_EABI__
3337
3338zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32);
3339static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); }
3340
3341zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32);
3342static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); }
3343
3344zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32);
3345static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); }
3346
3347zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t);
3348static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); }
3349
3350zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t);
3351static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); }
3352
3353zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t);
3354static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); }
3355
3356zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64);
3357static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); }
3358
3359zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64);
3360static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); }
3361
3362zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64);
3363static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); }
3364
3365zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t);
3366static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); }
3367
3368zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t);
3369static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); }
3370
3371zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t);
3372static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); }
3373
3374#else /* __ARM_EABI__ */
3375
3376zig_float_builtins(32)
3377zig_float_builtins(64)
3378
3379#endif /* __ARM_EABI__ */
3380
33183381/* ============================ Atomics Support ============================= */
33193382
33203383/* Note that atomics should be implemented as macros because most
src/Module.zig+3
......@@ -4186,6 +4186,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
41864186 .owner_decl = new_decl,
41874187 .owner_decl_index = new_decl_index,
41884188 .func_index = .none,
4189 .func_is_naked = false,
41894190 .fn_ret_ty = Type.void,
41904191 .fn_ret_ty_ies = null,
41914192 .owner_func_index = .none,
......@@ -4268,6 +4269,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
42684269 .owner_decl = decl,
42694270 .owner_decl_index = decl_index,
42704271 .func_index = .none,
4272 .func_is_naked = false,
42714273 .fn_ret_ty = Type.void,
42724274 .fn_ret_ty_ies = null,
42734275 .owner_func_index = .none,
......@@ -5213,6 +5215,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
52135215 .owner_decl = decl,
52145216 .owner_decl_index = decl_index,
52155217 .func_index = func_index,
5218 .func_is_naked = fn_ty_info.cc == .Naked,
52165219 .fn_ret_ty = fn_ty_info.return_type.toType(),
52175220 .fn_ret_ty_ies = null,
52185221 .owner_func_index = func_index,
src/Sema.zig+28-3
......@@ -30,6 +30,8 @@ owner_func_index: InternPool.Index,
3030/// an inline or comptime function call.
3131/// This could be `none`, a `func_decl`, or a `func_instance`.
3232func_index: InternPool.Index,
33/// Whether the type of func_index has a calling convention of `.Naked`.
34func_is_naked: bool,
3335/// Used to restore the error return trace when returning a non-error from a function.
3436error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
3537/// When semantic analysis needs to know the return type of the function whose body
......@@ -6827,6 +6829,10 @@ fn analyzeCall(
68276829 var is_inline_call = is_comptime_call or modifier == .always_inline or
68286830 func_ty_info.cc == .Inline;
68296831
6832 if (sema.func_is_naked and !is_inline_call and !is_comptime_call) {
6833 return sema.fail(block, call_src, "runtime call not allowed in naked function", .{});
6834 }
6835
68306836 if (!is_inline_call and is_generic_call) {
68316837 if (sema.instantiateGenericCall(
68326838 block,
......@@ -7509,6 +7515,9 @@ fn instantiateGenericCall(
75097515 .owner_decl = sema.owner_decl,
75107516 .owner_decl_index = sema.owner_decl_index,
75117517 .func_index = sema.owner_func_index,
7518 // This may not be known yet, since the calling convention could be generic, but there
7519 // should be no illegal instructions encountered while creating the function anyway.
7520 .func_is_naked = false,
75127521 .fn_ret_ty = Type.void,
75137522 .fn_ret_ty_ies = null,
75147523 .owner_func_index = .none,
......@@ -18193,10 +18202,20 @@ fn zirRetImplicit(
1819318202 const tracy = trace(@src());
1819418203 defer tracy.end();
1819518204
18205 if (block.inlining == null and sema.func_is_naked) {
18206 assert(!block.is_comptime);
18207 if (block.wantSafety()) {
18208 // Calling a safety function from a naked function would not be legal.
18209 _ = try block.addNoOp(.trap);
18210 } else {
18211 try block.addUnreachable(false);
18212 }
18213 return always_noreturn;
18214 }
18215
1819618216 const mod = sema.mod;
1819718217 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;
1819818218 const operand = try sema.resolveInst(inst_data.operand);
18199
1820018219 const r_brace_src = inst_data.src();
1820118220 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
1820218221 const base_tag = sema.fn_ret_ty.baseZigTypeTag(mod);
......@@ -18222,7 +18241,7 @@ fn zirRetImplicit(
1822218241 return sema.failWithOwnedErrorMsg(msg);
1822318242 }
1822418243
18225 return sema.analyzeRet(block, operand, .unneeded);
18244 return sema.analyzeRet(block, operand, r_brace_src);
1822618245}
1822718246
1822818247fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {
......@@ -18244,7 +18263,7 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir
1824418263 const src = inst_data.src();
1824518264 const ret_ptr = try sema.resolveInst(inst_data.operand);
1824618265
18247 if (block.is_comptime or block.inlining != null) {
18266 if (block.is_comptime or block.inlining != null or sema.func_is_naked) {
1824818267 const operand = try sema.analyzeLoad(block, src, ret_ptr, src);
1824918268 return sema.analyzeRet(block, operand, src);
1825018269 }
......@@ -18450,6 +18469,8 @@ fn analyzeRet(
1845018469 return always_noreturn;
1845118470 } else if (block.is_comptime) {
1845218471 return sema.fail(block, src, "function called at runtime cannot return value at comptime", .{});
18472 } else if (sema.func_is_naked) {
18473 return sema.fail(block, src, "cannot return from naked function", .{});
1845318474 }
1845418475
1845518476 try sema.resolveTypeLayout(sema.fn_ret_ty);
......@@ -33571,6 +33592,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3357133592 .owner_decl = decl,
3357233593 .owner_decl_index = decl_index,
3357333594 .func_index = .none,
33595 .func_is_naked = false,
3357433596 .fn_ret_ty = Type.void,
3357533597 .fn_ret_ty_ies = null,
3357633598 .owner_func_index = .none,
......@@ -33622,6 +33644,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
3362233644 .owner_decl = decl,
3362333645 .owner_decl_index = decl_index,
3362433646 .func_index = .none,
33647 .func_is_naked = false,
3362533648 .fn_ret_ty = Type.void,
3362633649 .fn_ret_ty_ies = null,
3362733650 .owner_func_index = .none,
......@@ -34405,6 +34428,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
3440534428 .owner_decl = decl,
3440634429 .owner_decl_index = decl_index,
3440734430 .func_index = .none,
34431 .func_is_naked = false,
3440834432 .fn_ret_ty = Type.void,
3440934433 .fn_ret_ty_ies = null,
3441034434 .owner_func_index = .none,
......@@ -34748,6 +34772,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
3474834772 .owner_decl = decl,
3474934773 .owner_decl_index = decl_index,
3475034774 .func_index = .none,
34775 .func_is_naked = false,
3475134776 .fn_ret_ty = Type.void,
3475234777 .fn_ret_ty_ies = null,
3475334778 .owner_func_index = .none,
src/TypedValue.zig+1
......@@ -196,6 +196,7 @@ pub fn print(
196196 .undef => return writer.writeAll("undefined"),
197197 .runtime_value => return writer.writeAll("(runtime value)"),
198198 .simple_value => |simple_value| switch (simple_value) {
199 .void => return writer.writeAll("{}"),
199200 .empty_struct => return printAggregate(ty, val, writer, level, mod),
200201 .generic_poison => return writer.writeAll("(generic poison)"),
201202 else => return writer.writeAll(@tagName(simple_value)),
src/arch/x86_64/CodeGen.zig+155-54
......@@ -177,7 +177,7 @@ pub const MCValue = union(enum) {
177177 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.
178178 register_overflow: struct { reg: Register, eflags: Condition },
179179 /// 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.
181181 memory: u64,
182182 /// The value is in memory at a constant offset from the address in a register.
183183 indirect: RegisterOffset,
......@@ -300,7 +300,7 @@ pub const MCValue = union(enum) {
300300 .load_tlv,
301301 .load_frame,
302302 .reserved_frame,
303 => unreachable, // not a dereferenceable
303 => unreachable, // not dereferenceable
304304 .immediate => |addr| .{ .memory = addr },
305305 .register => |reg| .{ .indirect = .{ .reg = reg } },
306306 .register_offset => |reg_off| .{ .indirect = reg_off },
......@@ -3468,14 +3468,14 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
34683468 const mod = self.bin_file.options.module.?;
34693469 const abi_size: u32 = @intCast(ty.abiSize(mod));
34703470 const int_info = ty.intInfo(mod);
3471 const dividend: Register = switch (lhs) {
3471 const dividend = switch (lhs) {
34723472 .register => |reg| reg,
34733473 else => try self.copyToTmpRegister(ty, lhs),
34743474 };
34753475 const dividend_lock = self.register_manager.lockReg(dividend);
34763476 defer if (dividend_lock) |lock| self.register_manager.unlockReg(lock);
34773477
3478 const divisor: Register = switch (rhs) {
3478 const divisor = switch (rhs) {
34793479 .register => |reg| reg,
34803480 else => try self.copyToTmpRegister(ty, rhs),
34813481 };
......@@ -9184,6 +9184,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
91849184}
91859185
91869186fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9187 const mod = self.bin_file.options.module.?;
91879188 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
91889189 const extra = self.air.extraData(Air.Asm, ty_pl.payload);
91899190 const clobbers_len: u31 = @truncate(extra.data.flags);
......@@ -9196,23 +9197,15 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
91969197
91979198 var result: MCValue = .none;
91989199 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);
92009201 defer {
9201 for (args.values()) |arg| switch (arg) {
9202 .register => |reg| self.register_manager.unlockReg(.{ .register = reg }),
9203 else => {},
9204 };
9202 for (args.values()) |arg| if (arg.getReg()) |reg|
9203 self.register_manager.unlockReg(.{ .register = reg });
92059204 args.deinit();
92069205 }
92079206
9208 if (outputs.len > 1) {
9209 return self.fail("TODO implement codegen for asm with more than 1 output", .{});
9210 }
9211
9207 var outputs_extra_i = extra_i;
92129208 for (outputs) |output| {
9213 if (output != .none) {
9214 return self.fail("TODO implement codegen for non-expr asm", .{});
9215 }
92169209 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
92179210 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
92189211 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
......@@ -9220,21 +9213,48 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
92209213 // for the string, we still use the next u32 for the null terminator.
92219214 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
92229215
9223 const mcv: MCValue = if (mem.eql(u8, constraint, "=r"))
9224 .{ .register = self.register_manager.tryAllocReg(inst, gp) orelse
9225 return self.fail("ran out of registers lowering inline asm", .{}) }
9216 const maybe_inst = switch (output) {
9217 .none => inst,
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 )
92269238 else if (mem.startsWith(u8, constraint, "={") and mem.endsWith(u8, constraint, "}"))
9227 .{ .register = parseRegName(constraint["={".len .. constraint.len - "}".len]) orelse
9228 return self.fail("unrecognized register constraint: '{s}'", .{constraint}) }
9239 parseRegName(constraint["={".len .. constraint.len - "}".len]) orelse
9240 return self.fail("invalid register constraint: '{s}'", .{constraint})
92299241 else
9230 return self.fail("unrecognized constraint: '{s}'", .{constraint});
9231 args.putAssumeCapacity(name, mcv);
9232 switch (mcv) {
9233 .register => |reg| _ = if (RegisterManager.indexOfRegIntoTracked(reg)) |_|
9234 self.register_manager.lockRegAssumeUnused(reg),
9235 else => {},
9236 }
9237 if (output == .none) result = mcv;
9242 return self.fail("invalid constraint: '{s}'", .{constraint});
9243 const arg_mcv: MCValue = if (arg_maybe_reg) |reg| .{ .register = reg } else arg: {
9244 const ptr_mcv = try self.resolveInst(output);
9245 switch (ptr_mcv) {
9246 .immediate => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
9247 break :arg ptr_mcv.deref(),
9248 .register, .register_offset, .lea_frame => break :arg ptr_mcv.deref(),
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;
92389258 }
92399259
92409260 for (inputs) |input| {
......@@ -9245,16 +9265,53 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
92459265 // for the string, we still use the next u32 for the null terminator.
92469266 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
92479267
9248 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {
9249 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});
9250 }
9251 const reg_name = constraint[1 .. constraint.len - 1];
9252 const reg = parseRegName(reg_name) orelse
9253 return self.fail("unrecognized register: '{s}'", .{reg_name});
9254
9255 const arg_mcv = try self.resolveInst(input);
9256 try self.register_manager.getReg(reg, null);
9257 try self.genSetReg(reg, self.typeOf(input), arg_mcv);
9268 const ty = self.typeOf(input);
9269 const input_mcv = try self.resolveInst(input);
9270 const arg_mcv: MCValue = if (mem.eql(u8, constraint, "r")) switch (input_mcv) {
9271 .register => input_mcv,
9272 else => .{ .register = try self.copyToTmpRegister(ty, input_mcv) },
9273 } else if (mem.eql(u8, constraint, "m")) arg: {
9274 switch (input_mcv) {
9275 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
9276 break :arg input_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);
92589315 }
92599316
92609317 {
......@@ -9293,7 +9350,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
92939350 }
92949351 }
92959352 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});
92979354 } };
92989355
92999356 var op_it = mem.tokenizeScalar(u8, mnem_it.rest(), ',');
......@@ -9304,43 +9361,73 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
93049361 if (mem.startsWith(u8, op_str, "%%")) {
93059362 const colon = mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');
93069363 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});
93089365 if (colon) |colon_pos| {
93099366 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});
93119368 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}),
93139370 .{ .base = .{ .reg = reg }, .disp = disp },
93149371 ) };
93159372 } else {
93169373 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});
93189375 op.* = .{ .reg = reg };
93199376 }
93209377 } else if (mem.startsWith(u8, op_str, "%[") and mem.endsWith(u8, op_str, "]")) {
9321 switch (args.get(op_str["%[".len .. op_str.len - "]".len]) orelse
9322 return self.fail("No matching constraint: '{s}'", .{op_str})) {
9323 .register => |reg| op.* = .{ .reg = reg },
9324 else => return self.fail("Invalid constraint: '{s}'", .{op_str}),
9325 }
9378 const colon = mem.indexOfScalarPos(u8, op_str, "%[".len, ':');
9379 const modifier = if (colon) |colon_pos|
9380 op_str[colon_pos + 1 .. op_str.len - "]".len]
9381 else
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 };
93269413 } else if (mem.startsWith(u8, op_str, "$")) {
93279414 if (std.fmt.parseInt(i32, op_str["$".len..], 0)) |s| {
93289415 if (mnem_size) |size| {
93299416 const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - (size.bitSize() - 1));
93309417 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});
93329419 }
93339420 op.* = .{ .imm = Immediate.s(s) };
93349421 } else |_| if (std.fmt.parseInt(u64, op_str["$".len..], 0)) |u| {
93359422 if (mnem_size) |size| {
93369423 const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - size.bitSize());
93379424 if (u > max)
9338 return self.fail("Invalid immediate size: '{s}'", .{op_str});
9425 return self.fail("invalid immediate size: '{s}'", .{op_str});
93399426 }
93409427 op.* = .{ .imm = Immediate.u(u) };
9341 } else |_| return self.fail("Invalid immediate: '{s}'", .{op_str});
9342 } 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});
9428 } else |_| return self.fail("invalid immediate: '{s}'", .{op_str});
9429 } else return self.fail("invalid operand: '{s}'", .{op_str});
9430 } else if (op_it.next()) |op_str| return self.fail("extra operand: '{s}'", .{op_str});
93449431
93459432 (switch (ops[0]) {
93469433 .none => self.asmOpOnly(mnem_tag),
......@@ -9407,6 +9494,20 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
94079494 };
94089495 }
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
94109511 simple: {
94119512 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);
94129513 var buf_index: usize = 0;
src/codegen/c.zig+52-35
......@@ -30,7 +30,7 @@ pub const CValue = union(enum) {
3030 /// Address of a local.
3131 local_ref: LocalIndex,
3232 /// A constant instruction, to be rendered inline.
33 constant: Air.Inst.Ref,
33 constant: InternPool.Index,
3434 /// Index into the parameters
3535 arg: usize,
3636 /// The array field of a parameter
......@@ -302,7 +302,7 @@ pub const Function = struct {
302302 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
303303 try writer.writeAll(";\n ");
304304 break :result decl_c_value;
305 } else .{ .constant = ref };
305 } else .{ .constant = val.toIntern() };
306306
307307 gop.value_ptr.* = result;
308308 return result;
......@@ -352,57 +352,63 @@ pub const Function = struct {
352352
353353 fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void {
354354 switch (c_value) {
355 .constant => |inst| {
356 const mod = f.object.dg.module;
357 const ty = f.typeOf(inst);
358 const val = (try f.air.value(inst, mod)).?;
359 return f.object.dg.renderValue(w, ty, val, location);
360 },
361 .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location),
362 else => return f.object.dg.writeCValue(w, c_value),
355 .constant => |val| try f.object.dg.renderValue(
356 w,
357 f.object.dg.module.intern_pool.typeOf(val).toType(),
358 val.toValue(),
359 location,
360 ),
361 .undef => |ty| try f.object.dg.renderValue(w, ty, Value.undef, location),
362 else => try f.object.dg.writeCValue(w, c_value),
363363 }
364364 }
365365
366366 fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void {
367367 switch (c_value) {
368 .constant => |inst| {
369 const mod = f.object.dg.module;
370 const ty = f.typeOf(inst);
371 const val = (try f.air.value(inst, mod)).?;
368 .constant => |val| {
372369 try w.writeAll("(*");
373 try f.object.dg.renderValue(w, ty, val, .Other);
374 return w.writeByte(')');
370 try f.object.dg.renderValue(
371 w,
372 f.object.dg.module.intern_pool.typeOf(val).toType(),
373 val.toValue(),
374 .Other,
375 );
376 try w.writeByte(')');
375377 },
376 else => return f.object.dg.writeCValueDeref(w, c_value),
378 else => try f.object.dg.writeCValueDeref(w, c_value),
377379 }
378380 }
379381
380382 fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
381383 switch (c_value) {
382 .constant => |inst| {
383 const mod = f.object.dg.module;
384 const ty = f.typeOf(inst);
385 const val = (try f.air.value(inst, mod)).?;
386 try f.object.dg.renderValue(w, ty, val, .Other);
384 .constant => |val| {
385 try f.object.dg.renderValue(
386 w,
387 f.object.dg.module.intern_pool.typeOf(val).toType(),
388 val.toValue(),
389 .Other,
390 );
387391 try w.writeByte('.');
388 return f.writeCValue(w, member, .Other);
392 try f.writeCValue(w, member, .Other);
389393 },
390 else => return f.object.dg.writeCValueMember(w, c_value, member),
394 else => try f.object.dg.writeCValueMember(w, c_value, member),
391395 }
392396 }
393397
394398 fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
395399 switch (c_value) {
396 .constant => |inst| {
397 const mod = f.object.dg.module;
398 const ty = f.typeOf(inst);
399 const val = (try f.air.value(inst, mod)).?;
400 .constant => |val| {
400401 try w.writeByte('(');
401 try f.object.dg.renderValue(w, ty, val, .Other);
402 try f.object.dg.renderValue(
403 w,
404 f.object.dg.module.intern_pool.typeOf(val).toType(),
405 val.toValue(),
406 .Other,
407 );
402408 try w.writeAll(")->");
403 return f.writeCValue(w, member, .Other);
409 try f.writeCValue(w, member, .Other);
404410 },
405 else => return f.object.dg.writeCValueDerefMember(w, c_value, member),
411 else => try f.object.dg.writeCValueDerefMember(w, c_value, member),
406412 }
407413 }
408414
......@@ -4763,11 +4769,22 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
47634769 return .none;
47644770}
47654771
4766fn asmInputNeedsLocal(constraint: []const u8, value: CValue) bool {
4772fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool {
4773 const target = f.object.dg.module.getTarget();
47674774 return switch (constraint[0]) {
47684775 '{' => true,
47694776 'i', 'r' => false,
4770 else => value == .constant,
4777 'I' => !target.cpu.arch.isArmOrThumb(),
4778 else => switch (value) {
4779 .constant => |val| switch (f.object.dg.module.intern_pool.indexToKey(val)) {
4780 .ptr => |ptr| switch (ptr.addr) {
4781 .decl => false,
4782 else => true,
4783 },
4784 else => true,
4785 },
4786 else => false,
4787 },
47714788 };
47724789}
47734790
......@@ -4848,7 +4865,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
48484865
48494866 const is_reg = constraint[0] == '{';
48504867 const input_val = try f.resolveInst(input);
4851 if (asmInputNeedsLocal(constraint, input_val)) {
4868 if (asmInputNeedsLocal(f, constraint, input_val)) {
48524869 const input_ty = f.typeOf(input);
48534870 if (is_reg) try writer.writeAll("register ");
48544871 const alignment = 0;
......@@ -4969,7 +4986,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
49694986 const is_reg = constraint[0] == '{';
49704987 const input_val = try f.resolveInst(input);
49714988 try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)});
4972 try f.writeCValue(writer, if (asmInputNeedsLocal(constraint, input_val)) local: {
4989 try f.writeCValue(writer, if (asmInputNeedsLocal(f, constraint, input_val)) local: {
49734990 const input_local = .{ .local = locals_index };
49744991 locals_index += 1;
49754992 break :local input_local;
src/codegen/llvm.zig+9-7
......@@ -417,7 +417,7 @@ const DataLayoutBuilder = struct {
417417 if (idx != size) try writer.print(":{d}", .{idx});
418418 }
419419 }
420 if (self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb())
420 if (self.target.cpu.arch.isArmOrThumb())
421421 try writer.writeAll("-Fi8"); // for thumb interwork
422422 if (self.target.cpu.arch != .hexagon) {
423423 if (self.target.cpu.arch == .s390x) try self.typeAlignment(.integer, 1, 8, 8, false, writer);
......@@ -620,7 +620,7 @@ const DataLayoutBuilder = struct {
620620 else => {},
621621 }
622622 },
623 .vector => if (self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb()) {
623 .vector => if (self.target.cpu.arch.isArmOrThumb()) {
624624 switch (size) {
625625 128 => abi = 64,
626626 else => {},
......@@ -670,7 +670,7 @@ const DataLayoutBuilder = struct {
670670 else => {},
671671 },
672672 .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())
674674 {
675675 pref = @min(pref, self.target.ptrBitWidth());
676676 } else if (self.target.cpu.arch == .hexagon) {
......@@ -6809,8 +6809,6 @@ pub const FuncGen = struct {
68096809 }
68106810 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);
68146812 if (output != .none) {
68156813 const output_inst = try self.resolveInst(output);
68166814 const output_ty = self.typeOf(output);
......@@ -6825,6 +6823,8 @@ pub const FuncGen = struct {
68256823 }),
68266824 }
68276825
6826 // Pass any non-return outputs indirectly, if the constraint accepts a memory location
6827 is_indirect.* = constraintAllowsMemory(constraint);
68286828 if (is_indirect.*) {
68296829 // Pass the result by reference as an indirect output (e.g. "=*m")
68306830 llvm_constraints.appendAssumeCapacity('*');
......@@ -6841,11 +6841,13 @@ pub const FuncGen = struct {
68416841 } else {
68426842 switch (constraint[0]) {
68436843 '=' => {},
6844 else => return self.todo("unsupported output constraint on result type '{c}'", .{
6845 constraint[0],
6844 else => return self.todo("unsupported output constraint on result type '{s}'", .{
6845 constraint,
68466846 }),
68476847 }
68486848
6849 is_indirect.* = false;
6850
68496851 const ret_ty = self.typeOfIndex(inst);
68506852 llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty);
68516853 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
16541654 }
16551655
16561656 if (self.base.options.link_mode == .Static) {
1657 if (target.cpu.arch.isARM() or target.cpu.arch.isThumb()) {
1657 if (target.cpu.arch.isArmOrThumb()) {
16581658 try argv.append("-Bstatic");
16591659 } else {
16601660 try argv.append("-static");
test/behavior/align.zig+3-2
......@@ -198,11 +198,12 @@ test "alignment and size of structs with 128-bit fields" {
198198
199199 else => return error.SkipZigTest,
200200 };
201 const min_struct_align = if (builtin.zig_backend == .stage2_c) 16 else 0;
201202 comptime {
202 assert(@alignOf(A) == expected.a_align);
203 assert(@alignOf(A) == @max(expected.a_align, min_struct_align));
203204 assert(@sizeOf(A) == expected.a_size);
204205
205 assert(@alignOf(B) == expected.b_align);
206 assert(@alignOf(B) == @max(expected.b_align, min_struct_align));
206207 assert(@sizeOf(B) == expected.b_size);
207208
208209 assert(@alignOf(u128) == expected.u128_align);
test/behavior/bitcast.zig+1-1
......@@ -421,7 +421,7 @@ test "bitcast nan float does modify signaling bit" {
421421 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
422422 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
423423 // 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
426426 // 16 bit
427427 const snan_f16_const = math.nan_f16;
test/behavior/call_tail.zig+10-1
......@@ -32,7 +32,16 @@ noinline fn insertionSort(data: []u64) void {
3232
3333test "arguments pointed to on stack into tailcall" {
3434 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,
3645 else => {},
3746 }
3847 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
test/behavior/cast.zig+2
......@@ -123,6 +123,7 @@ test "@floatFromInt(f80)" {
123123 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
124124 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
125125 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
126 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
126127
127128 const S = struct {
128129 fn doTheTest(comptime Int: type) !void {
......@@ -1369,6 +1370,7 @@ test "cast f16 to wider types" {
13691370 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
13701371 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13711372 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1373 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
13721374
13731375 const S = struct {
13741376 fn doTheTest() !void {
test/behavior/eval.zig+1
......@@ -533,6 +533,7 @@ test "runtime 128 bit integer division" {
533533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
534534 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
535535 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
536 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
536537
537538 var a: u128 = 152313999999999991610955792383;
538539 var b: u128 = 10000000000000000000;
test/behavior/floatop.zig+9
......@@ -554,6 +554,7 @@ test "another, possibly redundant, @fabs test" {
554554 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
555555 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
556556 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
557 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
557558
558559 try testFabsLegacy(f128, 12.0);
559560 try comptime testFabsLegacy(f128, 12.0);
......@@ -576,6 +577,7 @@ test "@fabs f80" {
576577 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
577578 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
578579 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
580 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
579581
580582 try testFabsLegacy(f80, 12.0);
581583 try comptime testFabsLegacy(f80, 12.0);
......@@ -593,6 +595,7 @@ test "a third @fabs test, surely there should not be three fabs tests" {
593595 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
594596 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
595597 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
598 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
596599
597600 inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {
598601 // normals
......@@ -684,6 +687,7 @@ test "@floor f80" {
684687 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
685688 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
686689 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
690 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
687691
688692 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
689693 // https://github.com/ziglang/zig/issues/12602
......@@ -700,6 +704,7 @@ test "@floor f128" {
700704 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
701705 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
702706 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
707 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
703708
704709 try testFloorLegacy(f128, 12.0);
705710 try comptime testFloorLegacy(f128, 12.0);
......@@ -780,6 +785,7 @@ test "@ceil f80" {
780785 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
781786 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
782787 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
788 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
783789
784790 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
785791 // https://github.com/ziglang/zig/issues/12602
......@@ -796,6 +802,7 @@ test "@ceil f128" {
796802 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
797803 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
798804 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
805 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
799806
800807 try testCeilLegacy(f128, 12.0);
801808 try comptime testCeilLegacy(f128, 12.0);
......@@ -875,6 +882,7 @@ test "@trunc f80" {
875882 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
876883 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
877884 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
885 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
878886
879887 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
880888 // https://github.com/ziglang/zig/issues/12602
......@@ -897,6 +905,7 @@ test "@trunc f128" {
897905 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
898906 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
899907 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
908 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
900909
901910 try testTruncLegacy(f128, 12.0);
902911 try comptime testTruncLegacy(f128, 12.0);
test/behavior/fn.zig+1
......@@ -151,6 +151,7 @@ fn fnWithUnreachable() noreturn {
151151
152152test "extern struct with stdcallcc fn pointer" {
153153 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
154 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .x86) return error.SkipZigTest;
154155 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
155156
156157 const S = extern struct {
test/behavior/math.zig+4
......@@ -664,6 +664,7 @@ test "128-bit multiplication" {
664664 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
665665 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
666666 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
667 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
667668
668669 {
669670 var a: i128 = 3;
......@@ -1311,6 +1312,7 @@ test "remainder division" {
13111312 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
13121313 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
13131314 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1315 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
13141316
13151317 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
13161318 // https://github.com/ziglang/zig/issues/12602
......@@ -1455,6 +1457,7 @@ test "@round f80" {
14551457 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14561458 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14571459 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1460 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
14581461
14591462 try testRound(f80, 12.0);
14601463 try comptime testRound(f80, 12.0);
......@@ -1467,6 +1470,7 @@ test "@round f128" {
14671470 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
14681471 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
14691472 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1473 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
14701474
14711475 try testRound(f128, 12.0);
14721476 try comptime testRound(f128, 12.0);
test/behavior/maximum_minimum.zig+1
......@@ -110,6 +110,7 @@ test "@min/max for floats" {
110110 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
111111 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
112112 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
113 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
113114
114115 const S = struct {
115116 fn doTheTest(comptime T: type) !void {
test/behavior/muladd.zig+4
......@@ -56,6 +56,7 @@ test "@mulAdd f80" {
5656 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
5757 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
5858 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
59 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
5960
6061 try comptime testMulAdd80();
6162 try testMulAdd80();
......@@ -75,6 +76,7 @@ test "@mulAdd f128" {
7576 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
7677 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
7778 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
79 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
7880
7981 try comptime testMulAdd128();
8082 try testMulAdd128();
......@@ -177,6 +179,7 @@ test "vector f80" {
177179 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
178180 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
179181 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
182 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
180183
181184 try comptime vector80();
182185 try vector80();
......@@ -201,6 +204,7 @@ test "vector f128" {
201204 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
202205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
203206 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
207 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
204208
205209 try comptime vector128();
206210 try vector128();
test/behavior/saturating_arithmetic.zig+1
......@@ -157,6 +157,7 @@ test "saturating multiplication" {
157157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
158158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
159159 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
160 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
160161
161162 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .wasm32) {
162163 // https://github.com/ziglang/zig/issues/9660
test/behavior/struct.zig+3-2
......@@ -428,7 +428,7 @@ test "packed struct 24bits" {
428428 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
429429 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
430430 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO
431 if (builtin.cpu.arch == .arm) return error.SkipZigTest; // TODO
431 if (comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; // TODO
432432 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
433433 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
434434
......@@ -824,6 +824,7 @@ test "non-packed struct with u128 entry in union" {
824824 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
825825 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
826826 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
827 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
827828
828829 const U = union(enum) {
829830 Num: u128,
......@@ -944,7 +945,7 @@ test "comptime struct field" {
944945 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
945946
946947 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
947 if (builtin.cpu.arch == .arm) return error.SkipZigTest; // TODO
948 if (comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; // TODO
948949
949950 const T = struct {
950951 a: i32,
test/behavior/var_args.zig+4-4
......@@ -101,7 +101,7 @@ test "simple variadic function" {
101101 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
102102 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
103103 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()) {
105105 // https://github.com/ziglang/zig/issues/14096
106106 return error.SkipZigTest;
107107 }
......@@ -151,7 +151,7 @@ test "variadic functions" {
151151 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
152152 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
153153 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()) {
155155 // https://github.com/ziglang/zig/issues/14096
156156 return error.SkipZigTest;
157157 }
......@@ -195,7 +195,7 @@ test "copy VaList" {
195195 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
196196 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
197197 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()) {
199199 // https://github.com/ziglang/zig/issues/14096
200200 return error.SkipZigTest;
201201 }
......@@ -228,7 +228,7 @@ test "unused VaList arg" {
228228 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
229229 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
230230 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()) {
232232 // https://github.com/ziglang/zig/issues/14096
233233 return error.SkipZigTest;
234234 }
test/behavior/vector.zig+3
......@@ -102,6 +102,7 @@ test "vector float operators" {
102102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
103103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
104104 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
105 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
105106
106107 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
107108 const S = struct {
......@@ -494,6 +495,7 @@ test "vector division operators" {
494495 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
495496 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
496497 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;
497499 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
498500 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
499501
......@@ -705,6 +707,7 @@ test "vector reduce operation" {
705707 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
706708 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
707709 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
710 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
708711
709712 const S = struct {
710713 fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {
test/src/Cases.zig+1-1
......@@ -1524,7 +1524,7 @@ fn runOneCase(
15241524 }
15251525 } else switch (host.getExternalExecutor(target_info, .{ .link_libc = case.link_libc })) {
15261526 .native => {
1527 if (case.backend == .stage2 and case.target.getCpuArch() == .arm) {
1527 if (case.backend == .stage2 and case.target.getCpuArch().isArmOrThumb()) {
15281528 // https://github.com/ziglang/zig/issues/13623
15291529 continue :update; // Pass test.
15301530 }
test/tests.zig+1
......@@ -1053,6 +1053,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
10531053 // TODO stop violating these pedantic errors. spotted on linux
10541054 "-Wno-address-of-packed-member",
10551055 "-Wno-gnu-folding-constant",
1056 "-Wno-incompatible-function-pointer-types",
10561057 "-Wno-incompatible-pointer-types",
10571058 "-Wno-overlength-strings",
10581059 // TODO stop violating these pedantic errors. spotted on darwin