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 {...@@ -200,72 +200,67 @@ fn clone() callconv(.Naked) void {
200 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)200 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
201 // eax, ebx, ecx, edx, esi, edi201 // eax, ebx, ecx, edx, esi, edi
202 asm volatile (202 asm volatile (
203 \\ push %%ebp203 \\ pushl %%ebp
204 \\ mov %%esp,%%ebp204 \\ movl %%esp,%%ebp
205 \\ push %%ebx205 \\ pushl %%ebx
206 \\ push %%esi206 \\ pushl %%esi
207 \\ push %%edi207 \\ pushl %%edi
208 \\ // Setup the arguments208 \\ // Setup the arguments
209 \\ mov 16(%%ebp),%%ebx209 \\ movl 16(%%ebp),%%ebx
210 \\ mov 12(%%ebp),%%ecx210 \\ movl 12(%%ebp),%%ecx
211 \\ and $-16,%%ecx211 \\ andl $-16,%%ecx
212 \\ sub $20,%%ecx212 \\ subl $20,%%ecx
213 \\ mov 20(%%ebp),%%eax213 \\ movl 20(%%ebp),%%eax
214 \\ mov %%eax,4(%%ecx)214 \\ movl %%eax,4(%%ecx)
215 \\ mov 8(%%ebp),%%eax215 \\ movl 8(%%ebp),%%eax
216 \\ mov %%eax,0(%%ecx)216 \\ movl %%eax,0(%%ecx)
217 \\ mov 24(%%ebp),%%edx217 \\ movl 24(%%ebp),%%edx
218 \\ mov 28(%%ebp),%%esi218 \\ movl 28(%%ebp),%%esi
219 \\ mov 32(%%ebp),%%edi219 \\ movl 32(%%ebp),%%edi
220 \\ mov $120,%%eax220 \\ movl $120,%%eax
221 \\ int $128221 \\ int $128
222 \\ test %%eax,%%eax222 \\ testl %%eax,%%eax
223 \\ jnz 1f223 \\ jnz 1f
224 \\ pop %%eax224 \\ popl %%eax
225 \\ xor %%ebp,%%ebp225 \\ xorl %%ebp,%%ebp
226 \\ call *%%eax226 \\ calll *%%eax
227 \\ mov %%eax,%%ebx227 \\ movl %%eax,%%ebx
228 \\ xor %%eax,%%eax228 \\ movl $1,%%eax
229 \\ inc %%eax
230 \\ int $128229 \\ int $128
231 \\ hlt
232 \\1:230 \\1:
233 \\ pop %%edi231 \\ popl %%edi
234 \\ pop %%esi232 \\ popl %%esi
235 \\ pop %%ebx233 \\ popl %%ebx
236 \\ pop %%ebp234 \\ popl %%ebp
237 \\ ret235 \\ retl
238 );236 );
239 },237 },
240 .x86_64 => {238 .x86_64 => {
241 asm volatile (239 asm volatile (
242 \\ xor %%eax,%%eax240 \\ movl $56,%%eax // SYS_clone
243 \\ mov $56,%%al // SYS_clone241 \\ movq %%rdi,%%r11
244 \\ mov %%rdi,%%r11242 \\ movq %%rdx,%%rdi
245 \\ mov %%rdx,%%rdi243 \\ movq %%r8,%%rdx
246 \\ mov %%r8,%%rdx244 \\ movq %%r9,%%r8
247 \\ mov %%r9,%%r8245 \\ movq 8(%%rsp),%%r10
248 \\ mov 8(%%rsp),%%r10246 \\ movq %%r11,%%r9
249 \\ mov %%r11,%%r9247 \\ andq $-16,%%rsi
250 \\ and $-16,%%rsi248 \\ subq $8,%%rsi
251 \\ sub $8,%%rsi249 \\ movq %%rcx,(%%rsi)
252 \\ mov %%rcx,(%%rsi)
253 \\ syscall250 \\ syscall
254 \\ test %%eax,%%eax251 \\ testq %%rax,%%rax
255 \\ jnz 1f252 \\ jnz 1f
256 \\ xor %%ebp,%%ebp253 \\ xorl %%ebp,%%ebp
257 \\ pop %%rdi254 \\ popq %%rdi
258 \\ call *%%r9255 \\ callq *%%r9
259 \\ mov %%eax,%%edi256 \\ movl %%eax,%%edi
260 \\ xor %%eax,%%eax257 \\ movl $60,%%eax // SYS_exit
261 \\ mov $60,%%al // SYS_exit
262 \\ syscall258 \\ syscall
263 \\ hlt
264 \\1: ret259 \\1: ret
265 \\260 \\
266 );261 );
267 },262 },
268 .aarch64 => {263 .aarch64, .aarch64_be => {
269 // __clone(func, stack, flags, arg, ptid, tls, ctid)264 // __clone(func, stack, flags, arg, ptid, tls, ctid)
270 // x0, x1, w2, x3, x4, x5, x6265 // x0, x1, w2, x3, x4, x5, x6
271266
...@@ -400,69 +395,69 @@ fn clone() callconv(.Naked) void {...@@ -400,69 +395,69 @@ fn clone() callconv(.Naked) void {
400 \\ syscall395 \\ syscall
401 );396 );
402 },397 },
403 .powerpc => {398 .powerpc, .powerpcle => {
404 // __clone(func, stack, flags, arg, ptid, tls, ctid)399 // __clone(func, stack, flags, arg, ptid, tls, ctid)
405 // 3, 4, 5, 6, 7, 8, 9400 // 3, 4, 5, 6, 7, 8, 9
406401
407 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)402 // syscall(SYS_clone, flags, stack, ptid, tls, ctid)
408 // 0 3, 4, 5, 6, 7403 // 0 3, 4, 5, 6, 7
409 asm volatile (404 asm volatile (
410 \\# store non-volatile regs r30, r31 on stack in order to put our405 \\ # store non-volatile regs r30, r31 on stack in order to put our
411 \\# start func and its arg there406 \\ # start func and its arg there
412 \\stwu 30, -16(1)407 \\ stwu 30, -16(1)
413 \\stw 31, 4(1)408 \\ stw 31, 4(1)
414 \\409 \\
415 \\# save r3 (func) into r30, and r6(arg) into r31410 \\ # save r3 (func) into r30, and r6(arg) into r31
416 \\mr 30, 3411 \\ mr 30, 3
417 \\mr 31, 6412 \\ mr 31, 6
418 \\413 \\
419 \\# create initial stack frame for new thread414 \\ # create initial stack frame for new thread
420 \\clrrwi 4, 4, 4415 \\ clrrwi 4, 4, 4
421 \\li 0, 0416 \\ li 0, 0
422 \\stwu 0, -16(4)417 \\ stwu 0, -16(4)
423 \\418 \\
424 \\#move c into first arg419 \\ #move c into first arg
425 \\mr 3, 5420 \\ mr 3, 5
426 \\#mr 4, 4421 \\ #mr 4, 4
427 \\mr 5, 7422 \\ mr 5, 7
428 \\mr 6, 8423 \\ mr 6, 8
429 \\mr 7, 9424 \\ mr 7, 9
430 \\425 \\
431 \\# move syscall number into r0426 \\ # move syscall number into r0
432 \\li 0, 120427 \\ li 0, 120
433 \\428 \\
434 \\sc429 \\ sc
435 \\430 \\
436 \\# check for syscall error431 \\ # check for syscall error
437 \\bns+ 1f # jump to label 1 if no summary overflow.432 \\ bns+ 1f # jump to label 1 if no summary overflow.
438 \\#else433 \\ #else
439 \\neg 3, 3 #negate the result (errno)434 \\ neg 3, 3 #negate the result (errno)
440 \\1:435 \\ 1:
441 \\# compare sc result with 0436 \\ # compare sc result with 0
442 \\cmpwi cr7, 3, 0437 \\ cmpwi cr7, 3, 0
443 \\438 \\
444 \\# if not 0, jump to end439 \\ # if not 0, jump to end
445 \\bne cr7, 2f440 \\ bne cr7, 2f
446 \\441 \\
447 \\#else: we're the child442 \\ #else: we're the child
448 \\#call funcptr: move arg (d) into r3443 \\ #call funcptr: move arg (d) into r3
449 \\mr 3, 31444 \\ mr 3, 31
450 \\#move r30 (funcptr) into CTR reg445 \\ #move r30 (funcptr) into CTR reg
451 \\mtctr 30446 \\ mtctr 30
452 \\# call CTR reg447 \\ # call CTR reg
453 \\bctrl448 \\ bctrl
454 \\# mov SYS_exit into r0 (the exit param is already in r3)449 \\ # mov SYS_exit into r0 (the exit param is already in r3)
455 \\li 0, 1450 \\ li 0, 1
456 \\sc451 \\ sc
457 \\452 \\
458 \\2:453 \\ 2:
459 \\454 \\
460 \\# restore stack455 \\ # restore stack
461 \\lwz 30, 0(1)456 \\ lwz 30, 0(1)
462 \\lwz 31, 4(1)457 \\ lwz 31, 4(1)
463 \\addi 1, 1, 16458 \\ addi 1, 1, 16
464 \\459 \\
465 \\blr460 \\ blr
466 );461 );
467 },462 },
468 .powerpc64, .powerpc64le => {463 .powerpc64, .powerpc64le => {
lib/compiler_rt/arm.zig+1-1
...@@ -9,7 +9,7 @@ pub const panic = common.panic;...@@ -9,7 +9,7 @@ pub const panic = common.panic;
99
10comptime {10comptime {
11 if (!builtin.is_test) {11 if (!builtin.is_test) {
12 if (arch.isARM() or arch.isThumb()) {12 if (arch.isArmOrThumb()) {
13 @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = common.linkage, .visibility = common.visibility });13 @export(__aeabi_unwind_cpp_pr0, .{ .name = "__aeabi_unwind_cpp_pr0", .linkage = common.linkage, .visibility = common.visibility });
14 @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = common.linkage, .visibility = common.visibility });14 @export(__aeabi_unwind_cpp_pr1, .{ .name = "__aeabi_unwind_cpp_pr1", .linkage = common.linkage, .visibility = common.visibility });
15 @export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = common.linkage, .visibility = common.visibility });15 @export(__aeabi_unwind_cpp_pr2, .{ .name = "__aeabi_unwind_cpp_pr2", .linkage = common.linkage, .visibility = common.visibility });
lib/compiler_rt/clzsi2_test.zig+1-1
...@@ -268,7 +268,7 @@ test "clzsi2" {...@@ -268,7 +268,7 @@ test "clzsi2" {
268 try test__clzsi2(0xFE000000, 0);268 try test__clzsi2(0xFE000000, 0);
269 try test__clzsi2(0xFF000000, 0);269 try test__clzsi2(0xFF000000, 0);
270 // arm and thumb1 assume input a != 0270 // arm and thumb1 assume input a != 0
271 if (!builtin.cpu.arch.isARM() and !builtin.cpu.arch.isThumb())271 if (!builtin.cpu.arch.isArmOrThumb())
272 try test__clzsi2(0x00000000, 32);272 try test__clzsi2(0x00000000, 32);
273 try test__clzsi2(0x00000001, 31);273 try test__clzsi2(0x00000001, 31);
274 try test__clzsi2(0x00000002, 30);274 try test__clzsi2(0x00000002, 30);
lib/std/Thread.zig+8-6
...@@ -1275,12 +1275,14 @@ const LinuxThreadImpl = struct {...@@ -1275,12 +1275,14 @@ const LinuxThreadImpl = struct {
1275 .entry_number = os.linux.tls.tls_image.gdt_entry_number,1275 .entry_number = os.linux.tls.tls_image.gdt_entry_number,
1276 .base_addr = tls_ptr,1276 .base_addr = tls_ptr,
1277 .limit = 0xfffff,1277 .limit = 0xfffff,
1278 .seg_32bit = 1,1278 .flags = .{
1279 .contents = 0, // Data1279 .seg_32bit = 1,
1280 .read_exec_only = 0,1280 .contents = 0, // Data
1281 .limit_in_pages = 1,1281 .read_exec_only = 0,
1282 .seg_not_present = 0,1282 .limit_in_pages = 1,
1283 .useable = 1,1283 .seg_not_present = 0,
1284 .useable = 1,
1285 },
1284 };1286 };
1285 }1287 }
12861288
lib/std/builtin.zig+1-1
...@@ -568,7 +568,7 @@ pub const VaListX86_64 = extern struct {...@@ -568,7 +568,7 @@ pub const VaListX86_64 = extern struct {
568/// This data structure is used by the Zig language code generation and568/// This data structure is used by the Zig language code generation and
569/// therefore must be kept in sync with the compiler implementation.569/// therefore must be kept in sync with the compiler implementation.
570pub const VaList = switch (builtin.cpu.arch) {570pub const VaList = switch (builtin.cpu.arch) {
571 .aarch64 => switch (builtin.os.tag) {571 .aarch64, .aarch64_be => switch (builtin.os.tag) {
572 .windows => *u8,572 .windows => *u8,
573 .ios, .macos, .tvos, .watchos => *u8,573 .ios, .macos, .tvos, .watchos => *u8,
574 else => @compileError("disabled due to miscompilations"), // VaListAarch64,574 else => @compileError("disabled due to miscompilations"), // VaListAarch64,
lib/std/os/linux.zig+6-8
...@@ -35,13 +35,13 @@ const syscall_bits = switch (native_arch) {...@@ -35,13 +35,13 @@ const syscall_bits = switch (native_arch) {
35const arch_bits = switch (native_arch) {35const arch_bits = switch (native_arch) {
36 .x86 => @import("linux/x86.zig"),36 .x86 => @import("linux/x86.zig"),
37 .x86_64 => @import("linux/x86_64.zig"),37 .x86_64 => @import("linux/x86_64.zig"),
38 .aarch64 => @import("linux/arm64.zig"),38 .aarch64, .aarch64_be => @import("linux/arm64.zig"),
39 .arm, .thumb => @import("linux/arm-eabi.zig"),39 .arm, .thumb => @import("linux/arm-eabi.zig"),
40 .riscv64 => @import("linux/riscv64.zig"),40 .riscv64 => @import("linux/riscv64.zig"),
41 .sparc64 => @import("linux/sparc64.zig"),41 .sparc64 => @import("linux/sparc64.zig"),
42 .mips, .mipsel => @import("linux/mips.zig"),42 .mips, .mipsel => @import("linux/mips.zig"),
43 .mips64, .mips64el => @import("linux/mips64.zig"),43 .mips64, .mips64el => @import("linux/mips64.zig"),
44 .powerpc => @import("linux/powerpc.zig"),44 .powerpc, .powerpcle => @import("linux/powerpc.zig"),
45 .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"),45 .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"),
46 else => struct {},46 else => struct {},
47};47};
...@@ -98,13 +98,13 @@ pub const syscalls = @import("linux/syscalls.zig");...@@ -98,13 +98,13 @@ pub const syscalls = @import("linux/syscalls.zig");
98pub const SYS = switch (@import("builtin").cpu.arch) {98pub const SYS = switch (@import("builtin").cpu.arch) {
99 .x86 => syscalls.X86,99 .x86 => syscalls.X86,
100 .x86_64 => syscalls.X64,100 .x86_64 => syscalls.X64,
101 .aarch64 => syscalls.Arm64,101 .aarch64, .aarch64_be => syscalls.Arm64,
102 .arm, .thumb => syscalls.Arm,102 .arm, .thumb => syscalls.Arm,
103 .riscv64 => syscalls.RiscV64,103 .riscv64 => syscalls.RiscV64,
104 .sparc64 => syscalls.Sparc64,104 .sparc64 => syscalls.Sparc64,
105 .mips, .mipsel => syscalls.Mips,105 .mips, .mipsel => syscalls.Mips,
106 .mips64, .mips64el => syscalls.Mips64,106 .mips64, .mips64el => syscalls.Mips64,
107 .powerpc => syscalls.PowerPC,107 .powerpc, .powerpcle => syscalls.PowerPC,
108 .powerpc64, .powerpc64le => syscalls.PowerPC64,108 .powerpc64, .powerpc64le => syscalls.PowerPC64,
109 else => @compileError("The Zig Standard Library is missing syscall definitions for the target CPU architecture"),109 else => @compileError("The Zig Standard Library is missing syscall definitions for the target CPU architecture"),
110};110};
...@@ -1176,14 +1176,12 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact...@@ -1176,14 +1176,12 @@ pub fn sigaction(sig: u6, noalias act: ?*const Sigaction, noalias oact: ?*Sigact
1176 const mask_size = @sizeOf(@TypeOf(ksa.mask));1176 const mask_size = @sizeOf(@TypeOf(ksa.mask));
11771177
1178 if (act) |new| {1178 if (act) |new| {
1179 const restore_rt_ptr = &restore_rt;1179 const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) &restore_rt else &restore;
1180 const restore_ptr = &restore;
1181 const restorer_fn = if ((new.flags & SA.SIGINFO) != 0) restore_rt_ptr else restore_ptr;
1182 ksa = k_sigaction{1180 ksa = k_sigaction{
1183 .handler = new.handler.handler,1181 .handler = new.handler.handler,
1184 .flags = new.flags | SA.RESTORER,1182 .flags = new.flags | SA.RESTORER,
1185 .mask = undefined,1183 .mask = undefined,
1186 .restorer = @as(k_sigaction_funcs.restorer, @ptrCast(restorer_fn)),1184 .restorer = @ptrCast(restorer_fn),
1187 };1185 };
1188 @memcpy(@as([*]u8, @ptrCast(&ksa.mask))[0..mask_size], @as([*]const u8, @ptrCast(&new.mask)));1186 @memcpy(@as([*]u8, @ptrCast(&ksa.mask))[0..mask_size], @as([*]const u8, @ptrCast(&new.mask)));
1189 }1187 }
lib/std/os/linux/arm-eabi.zig+32-12
...@@ -103,20 +103,40 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;...@@ -103,20 +103,40 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;
103/// This matches the libc clone function.103/// This matches the libc clone function.
104pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;104pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
105105
106pub fn restore() callconv(.Naked) void {106pub fn restore() callconv(.Naked) noreturn {
107 return asm volatile ("svc #0"107 switch (@import("builtin").zig_backend) {
108 :108 .stage2_c => asm volatile (
109 : [number] "{r7}" (@intFromEnum(SYS.sigreturn)),109 \\ mov r7, %[number]
110 : "memory"110 \\ svc #0
111 );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 }
112}122}
113123
114pub fn restore_rt() callconv(.Naked) void {124pub fn restore_rt() callconv(.Naked) noreturn {
115 return asm volatile ("svc #0"125 switch (@import("builtin").zig_backend) {
116 :126 .stage2_c => asm volatile (
117 : [number] "{r7}" (@intFromEnum(SYS.rt_sigreturn)),127 \\ mov r7, %[number]
118 : "memory"128 \\ svc #0
119 );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 }
120}140}
121141
122pub const MMAP2_UNIT = 4096;142pub 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: *...@@ -105,16 +105,17 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *
105105
106pub const restore = restore_rt;106pub const restore = restore_rt;
107107
108pub fn restore_rt() callconv(.Naked) void {108pub fn restore_rt() callconv(.Naked) noreturn {
109 switch (@import("builtin").zig_backend) {109 switch (@import("builtin").zig_backend) {
110 .stage2_c => return asm volatile (110 .stage2_c => asm volatile (
111 \\ mov x8, %[number]111 \\ mov x8, %[number]
112 \\ svc #0112 \\ svc #0
113 :113 :
114 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),114 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
115 : "memory", "cc"115 : "memory", "cc"
116 ),116 ),
117 else => return asm volatile ("svc #0"117 else => asm volatile (
118 \\ svc #0
118 :119 :
119 : [number] "{x8}" (@intFromEnum(SYS.rt_sigreturn)),120 : [number] "{x8}" (@intFromEnum(SYS.rt_sigreturn)),
120 : "memory", "cc"121 : "memory", "cc"
lib/std/os/linux/mips.zig+6-4
...@@ -195,16 +195,18 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;...@@ -195,16 +195,18 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;
195/// This matches the libc clone function.195/// This matches the libc clone function.
196pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;196pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
197197
198pub fn restore() callconv(.Naked) void {198pub fn restore() callconv(.Naked) noreturn {
199 return asm volatile ("syscall"199 asm volatile (
200 \\ syscall
200 :201 :
201 : [number] "{$2}" (@intFromEnum(SYS.sigreturn)),202 : [number] "{$2}" (@intFromEnum(SYS.sigreturn)),
202 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"203 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"
203 );204 );
204}205}
205206
206pub fn restore_rt() callconv(.Naked) void {207pub fn restore_rt() callconv(.Naked) noreturn {
207 return asm volatile ("syscall"208 asm volatile (
209 \\ syscall
208 :210 :
209 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),211 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),
210 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"212 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"
lib/std/os/linux/mips64.zig+6-4
...@@ -180,16 +180,18 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;...@@ -180,16 +180,18 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;
180/// This matches the libc clone function.180/// This matches the libc clone function.
181pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;181pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
182182
183pub fn restore() callconv(.Naked) void {183pub fn restore() callconv(.Naked) noreturn {
184 return asm volatile ("syscall"184 asm volatile (
185 \\ syscall
185 :186 :
186 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),187 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),
187 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"188 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"
188 );189 );
189}190}
190191
191pub fn restore_rt() callconv(.Naked) void {192pub fn restore_rt() callconv(.Naked) noreturn {
192 return asm volatile ("syscall"193 asm volatile (
194 \\ syscall
193 :195 :
194 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),196 : [number] "{$2}" (@intFromEnum(SYS.rt_sigreturn)),
195 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"197 : "$1", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24", "$25", "hi", "lo", "memory"
lib/std/os/linux/powerpc.zig+3-2
...@@ -133,8 +133,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:...@@ -133,8 +133,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:
133133
134pub const restore = restore_rt;134pub const restore = restore_rt;
135135
136pub fn restore_rt() callconv(.Naked) void {136pub fn restore_rt() callconv(.Naked) noreturn {
137 return asm volatile ("sc"137 asm volatile (
138 \\ sc
138 :139 :
139 : [number] "{r0}" (@intFromEnum(SYS.rt_sigreturn)),140 : [number] "{r0}" (@intFromEnum(SYS.rt_sigreturn)),
140 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"141 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
lib/std/os/linux/powerpc64.zig+3-2
...@@ -133,8 +133,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:...@@ -133,8 +133,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:
133133
134pub const restore = restore_rt;134pub const restore = restore_rt;
135135
136pub fn restore_rt() callconv(.Naked) void {136pub fn restore_rt() callconv(.Naked) noreturn {
137 return asm volatile ("sc"137 asm volatile (
138 \\ sc
138 :139 :
139 : [number] "{r0}" (@intFromEnum(SYS.rt_sigreturn)),140 : [number] "{r0}" (@intFromEnum(SYS.rt_sigreturn)),
140 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"141 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
lib/std/os/linux/riscv64.zig+3-2
...@@ -101,8 +101,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *...@@ -101,8 +101,9 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *
101101
102pub const restore = restore_rt;102pub const restore = restore_rt;
103103
104pub fn restore_rt() callconv(.Naked) void {104pub fn restore_rt() callconv(.Naked) noreturn {
105 return asm volatile ("ecall"105 asm volatile (
106 \\ ecall
106 :107 :
107 : [number] "{x17}" (@intFromEnum(SYS.rt_sigreturn)),108 : [number] "{x17}" (@intFromEnum(SYS.rt_sigreturn)),
108 : "memory"109 : "memory"
lib/std/os/linux/thumb.zig+4-4
...@@ -141,8 +141,8 @@ pub fn syscall6(...@@ -141,8 +141,8 @@ pub fn syscall6(
141 );141 );
142}142}
143143
144pub fn restore() callconv(.Naked) void {144pub fn restore() callconv(.Naked) noreturn {
145 return asm volatile (145 asm volatile (
146 \\ mov r7, %[number]146 \\ mov r7, %[number]
147 \\ svc #0147 \\ svc #0
148 :148 :
...@@ -150,8 +150,8 @@ pub fn restore() callconv(.Naked) void {...@@ -150,8 +150,8 @@ pub fn restore() callconv(.Naked) void {
150 );150 );
151}151}
152152
153pub fn restore_rt() callconv(.Naked) void {153pub fn restore_rt() callconv(.Naked) noreturn {
154 return asm volatile (154 asm volatile (
155 \\ mov r7, %[number]155 \\ mov r7, %[number]
156 \\ svc #0156 \\ svc #0
157 :157 :
lib/std/os/linux/tls.zig+11-9
...@@ -48,7 +48,7 @@ const TLSVariant = enum {...@@ -48,7 +48,7 @@ const TLSVariant = enum {
48};48};
4949
50const tls_variant = switch (native_arch) {50const tls_variant = switch (native_arch) {
51 .arm, .armeb, .thumb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .mips64, .mips64el, .powerpc, .powerpc64, .powerpc64le => TLSVariant.VariantI,51 .arm, .armeb, .thumb, .aarch64, .aarch64_be, .riscv32, .riscv64, .mips, .mipsel, .mips64, .mips64el, .powerpc, .powerpcle, .powerpc64, .powerpc64le => TLSVariant.VariantI,
52 .x86_64, .x86, .sparc64 => TLSVariant.VariantII,52 .x86_64, .x86, .sparc64 => TLSVariant.VariantII,
53 else => @compileError("undefined tls_variant for this architecture"),53 else => @compileError("undefined tls_variant for this architecture"),
54};54};
...@@ -115,12 +115,14 @@ pub fn setThreadPointer(addr: usize) void {...@@ -115,12 +115,14 @@ pub fn setThreadPointer(addr: usize) void {
115 .entry_number = tls_image.gdt_entry_number,115 .entry_number = tls_image.gdt_entry_number,
116 .base_addr = addr,116 .base_addr = addr,
117 .limit = 0xfffff,117 .limit = 0xfffff,
118 .seg_32bit = 1,118 .flags = .{
119 .contents = 0, // Data119 .seg_32bit = 1,
120 .read_exec_only = 0,120 .contents = 0, // Data
121 .limit_in_pages = 1,121 .read_exec_only = 0,
122 .seg_not_present = 0,122 .limit_in_pages = 1,
123 .useable = 1,123 .seg_not_present = 0,
124 .useable = 1,
125 },
124 };126 };
125 const rc = std.os.linux.syscall1(.set_thread_area, @intFromPtr(&user_desc));127 const rc = std.os.linux.syscall1(.set_thread_area, @intFromPtr(&user_desc));
126 assert(rc == 0);128 assert(rc == 0);
...@@ -138,7 +140,7 @@ pub fn setThreadPointer(addr: usize) void {...@@ -138,7 +140,7 @@ pub fn setThreadPointer(addr: usize) void {
138 const rc = std.os.linux.syscall2(.arch_prctl, std.os.linux.ARCH.SET_FS, addr);140 const rc = std.os.linux.syscall2(.arch_prctl, std.os.linux.ARCH.SET_FS, addr);
139 assert(rc == 0);141 assert(rc == 0);
140 },142 },
141 .aarch64 => {143 .aarch64, .aarch64_be => {
142 asm volatile (144 asm volatile (
143 \\ msr tpidr_el0, %[addr]145 \\ msr tpidr_el0, %[addr]
144 :146 :
...@@ -160,7 +162,7 @@ pub fn setThreadPointer(addr: usize) void {...@@ -160,7 +162,7 @@ pub fn setThreadPointer(addr: usize) void {
160 const rc = std.os.linux.syscall1(.set_thread_area, addr);162 const rc = std.os.linux.syscall1(.set_thread_area, addr);
161 assert(rc == 0);163 assert(rc == 0);
162 },164 },
163 .powerpc => {165 .powerpc, .powerpcle => {
164 asm volatile (166 asm volatile (
165 \\ mr 2, %[addr]167 \\ mr 2, %[addr]
166 :168 :
lib/std/os/linux/x86.zig+57-57
...@@ -123,46 +123,40 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;...@@ -123,46 +123,40 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8;
123/// This matches the libc clone function.123/// This matches the libc clone function.
124pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;124pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize;
125125
126pub fn restore() callconv(.Naked) void {126pub fn restore() callconv(.Naked) noreturn {
127 switch (@import("builtin").zig_backend) {127 switch (@import("builtin").zig_backend) {
128 .stage2_c => asm volatile (128 .stage2_c => asm volatile (
129 \\ movl %[number], %%eax129 \\ movl %[number], %%eax
130 \\ int $0x80130 \\ int $0x80
131 \\ ret
132 :131 :
133 : [number] "i" (@intFromEnum(SYS.sigreturn)),132 : [number] "i" (@intFromEnum(SYS.sigreturn)),
134 : "memory"133 : "memory"
135 ),134 ),
136 else => asm volatile (135 else => asm volatile (
137 \\ int $0x80136 \\ int $0x80
138 \\ ret
139 :137 :
140 : [number] "{eax}" (@intFromEnum(SYS.sigreturn)),138 : [number] "{eax}" (@intFromEnum(SYS.sigreturn)),
141 : "memory"139 : "memory"
142 ),140 ),
143 }141 }
144 unreachable;
145}142}
146143
147pub fn restore_rt() callconv(.Naked) void {144pub fn restore_rt() callconv(.Naked) noreturn {
148 switch (@import("builtin").zig_backend) {145 switch (@import("builtin").zig_backend) {
149 .stage2_c => asm volatile (146 .stage2_c => asm volatile (
150 \\ movl %[number], %%eax147 \\ movl %[number], %%eax
151 \\ int $0x80148 \\ int $0x80
152 \\ ret
153 :149 :
154 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),150 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
155 : "memory"151 : "memory"
156 ),152 ),
157 else => asm volatile (153 else => asm volatile (
158 \\ int $0x80154 \\ int $0x80
159 \\ ret
160 :155 :
161 : [number] "{eax}" (@intFromEnum(SYS.rt_sigreturn)),156 : [number] "{eax}" (@intFromEnum(SYS.rt_sigreturn)),
162 : "memory"157 : "memory"
163 ),158 ),
164 }159 }
165 unreachable;
166}160}
167161
168pub const O = struct {162pub const O = struct {
...@@ -354,16 +348,19 @@ pub const ucontext_t = extern struct {...@@ -354,16 +348,19 @@ pub const ucontext_t = extern struct {
354348
355pub const Elf_Symndx = u32;349pub const Elf_Symndx = u32;
356350
357pub const user_desc = packed struct {351pub const user_desc = extern struct {
358 entry_number: u32,352 entry_number: u32,
359 base_addr: u32,353 base_addr: u32,
360 limit: u32,354 limit: u32,
361 seg_32bit: u1,355 flags: packed struct(u32) {
362 contents: u2,356 seg_32bit: u1,
363 read_exec_only: u1,357 contents: u2,
364 limit_in_pages: u1,358 read_exec_only: u1,
365 seg_not_present: u1,359 limit_in_pages: u1,
366 useable: u1,360 seg_not_present: u1,
361 useable: u1,
362 _: u25 = undefined,
363 },
367};364};
368365
369/// socketcall() call numbers366/// socketcall() call numbers
...@@ -398,77 +395,80 @@ noinline fn getContextReturnAddress() usize {...@@ -398,77 +395,80 @@ noinline fn getContextReturnAddress() usize {
398 return @returnAddress();395 return @returnAddress();
399}396}
400397
401pub fn getContextInternal() callconv(.Naked) void {398pub fn getContextInternal() callconv(.Naked) usize {
402 asm volatile (399 asm volatile (
403 \\ movl $0, (%[flags_offset])(%%edx)400 \\ movl $0, %[flags_offset:c](%%edx)
404 \\ movl $0, (%[link_offset])(%%edx)401 \\ movl $0, %[link_offset:c](%%edx)
405 \\ movl %%edi, (%[edi_offset])(%%edx)402 \\ movl %%edi, %[edi_offset:c](%%edx)
406 \\ movl %%esi, (%[esi_offset])(%%edx)403 \\ movl %%esi, %[esi_offset:c](%%edx)
407 \\ movl %%ebp, (%[ebp_offset])(%%edx)404 \\ movl %%ebp, %[ebp_offset:c](%%edx)
408 \\ movl %%ebx, (%[ebx_offset])(%%edx)405 \\ movl %%ebx, %[ebx_offset:c](%%edx)
409 \\ movl %%edx, (%[edx_offset])(%%edx)406 \\ movl %%edx, %[edx_offset:c](%%edx)
410 \\ movl %%ecx, (%[ecx_offset])(%%edx)407 \\ movl %%ecx, %[ecx_offset:c](%%edx)
411 \\ movl %%eax, (%[eax_offset])(%%edx)408 \\ movl %%eax, %[eax_offset:c](%%edx)
412 \\ movl (%%esp), %%ecx409 \\ movl (%%esp), %%ecx
413 \\ movl %%ecx, (%[eip_offset])(%%edx)410 \\ movl %%ecx, %[eip_offset:c](%%edx)
414 \\ leal 4(%%esp), %%ecx411 \\ leal 4(%%esp), %%ecx
415 \\ movl %%ecx, (%[esp_offset])(%%edx)412 \\ movl %%ecx, %[esp_offset:c](%%edx)
416 \\ xorl %%ecx, %%ecx413 \\ xorl %%ecx, %%ecx
417 \\ movw %%fs, %%cx414 \\ movw %%fs, %%cx
418 \\ movl %%ecx, (%[fs_offset])(%%edx)415 \\ movl %%ecx, %[fs_offset:c](%%edx)
419 \\ leal (%[regspace_offset])(%%edx), %%ecx416 \\ leal %[regspace_offset:c](%%edx), %%ecx
420 \\ movl %%ecx, (%[fpregs_offset])(%%edx)417 \\ movl %%ecx, %[fpregs_offset:c](%%edx)
421 \\ fnstenv (%%ecx)418 \\ fnstenv (%%ecx)
422 \\ fldenv (%%ecx)419 \\ fldenv (%%ecx)
423 \\ pushl %%ebx420 \\ pushl %%ebx
424 \\ pushl %%esi421 \\ pushl %%esi
425 \\ xorl %%ebx, %%ebx422 \\ xorl %%ebx, %%ebx
426 \\ movl %[sigaltstack], %%eax423 \\ movl %[sigaltstack], %%eax
427 \\ leal (%[stack_offset])(%%edx), %%ecx424 \\ leal %[stack_offset:c](%%edx), %%ecx
428 \\ int $0x80425 \\ int $0x80
429 \\ cmpl $0, %%eax426 \\ testl %%eax, %%eax
430 \\ jne return427 \\ jnz 0f
431 \\ movl %[sigprocmask], %%eax428 \\ movl %[sigprocmask], %%eax
432 \\ xorl %%ecx, %%ecx429 \\ xorl %%ecx, %%ecx
433 \\ leal (%[sigmask_offset])(%%edx), %%edx430 \\ leal %[sigmask_offset:c](%%edx), %%edx
434 \\ movl %[sigset_size], %%esi431 \\ movl %[sigset_size], %%esi
435 \\ int $0x80432 \\ int $0x80
436 \\ return:433 \\0:
437 \\ popl %%esi434 \\ popl %%esi
438 \\ popl %%ebx435 \\ popl %%ebx
436 \\ retl
439 :437 :
440 : [flags_offset] "p" (@offsetOf(ucontext_t, "flags")),438 : [flags_offset] "i" (@offsetOf(ucontext_t, "flags")),
441 [link_offset] "p" (@offsetOf(ucontext_t, "link")),439 [link_offset] "i" (@offsetOf(ucontext_t, "link")),
442 [edi_offset] "p" (comptime gpRegisterOffset(REG.EDI)),440 [edi_offset] "i" (comptime gpRegisterOffset(REG.EDI)),
443 [esi_offset] "p" (comptime gpRegisterOffset(REG.ESI)),441 [esi_offset] "i" (comptime gpRegisterOffset(REG.ESI)),
444 [ebp_offset] "p" (comptime gpRegisterOffset(REG.EBP)),442 [ebp_offset] "i" (comptime gpRegisterOffset(REG.EBP)),
445 [esp_offset] "p" (comptime gpRegisterOffset(REG.ESP)),443 [esp_offset] "i" (comptime gpRegisterOffset(REG.ESP)),
446 [ebx_offset] "p" (comptime gpRegisterOffset(REG.EBX)),444 [ebx_offset] "i" (comptime gpRegisterOffset(REG.EBX)),
447 [edx_offset] "p" (comptime gpRegisterOffset(REG.EDX)),445 [edx_offset] "i" (comptime gpRegisterOffset(REG.EDX)),
448 [ecx_offset] "p" (comptime gpRegisterOffset(REG.ECX)),446 [ecx_offset] "i" (comptime gpRegisterOffset(REG.ECX)),
449 [eax_offset] "p" (comptime gpRegisterOffset(REG.EAX)),447 [eax_offset] "i" (comptime gpRegisterOffset(REG.EAX)),
450 [eip_offset] "p" (comptime gpRegisterOffset(REG.EIP)),448 [eip_offset] "i" (comptime gpRegisterOffset(REG.EIP)),
451 [fs_offset] "p" (comptime gpRegisterOffset(REG.FS)),449 [fs_offset] "i" (comptime gpRegisterOffset(REG.FS)),
452 [fpregs_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")),450 [fpregs_offset] "i" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")),
453 [regspace_offset] "p" (@offsetOf(ucontext_t, "regspace")),451 [regspace_offset] "i" (@offsetOf(ucontext_t, "regspace")),
454 [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)),452 [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)),
455 [stack_offset] "p" (@offsetOf(ucontext_t, "stack")),453 [stack_offset] "i" (@offsetOf(ucontext_t, "stack")),
456 [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)),454 [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)),
457 [sigmask_offset] "p" (@offsetOf(ucontext_t, "sigmask")),455 [sigmask_offset] "i" (@offsetOf(ucontext_t, "sigmask")),
458 [sigset_size] "i" (linux.NSIG / 8),456 [sigset_size] "i" (linux.NSIG / 8),
459 : "memory", "eax", "ecx", "edx"457 : "cc", "memory", "eax", "ecx", "edx"
460 );458 );
461}459}
462460
463pub inline fn getcontext(context: *ucontext_t) usize {461pub inline fn getcontext(context: *ucontext_t) usize {
464 // This method is used so that getContextInternal can control462 // This method is used so that getContextInternal can control
465 // its prologue in order to read ESP from a constant offset.463 // 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;
467 return asm volatile (466 return asm volatile (
468 \\ call os.linux.x86.getContextInternal467 \\ calll %[getContextInternal:P]
469 : [ret] "={eax}" (-> usize),468 : [_] "={eax}" (-> usize),
470 : [context] "{edx}" (context),469 [_] "={edx}" (clobber_edx),
470 : [_] "{edx}" (context),
471 [getContextInternal] "X" (&getContextInternal),471 [getContextInternal] "X" (&getContextInternal),
472 : "memory", "ecx"472 : "cc", "memory", "ecx"
473 );473 );
474}474}
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:...@@ -107,25 +107,22 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid:
107107
108pub const restore = restore_rt;108pub const restore = restore_rt;
109109
110pub fn restore_rt() callconv(.Naked) void {110pub fn restore_rt() callconv(.Naked) noreturn {
111 switch (@import("builtin").zig_backend) {111 switch (@import("builtin").zig_backend) {
112 .stage2_c => asm volatile (112 .stage2_c => asm volatile (
113 \\ movl %[number], %%eax113 \\ movl %[number], %%eax
114 \\ syscall114 \\ syscall
115 \\ retq
116 :115 :
117 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),116 : [number] "i" (@intFromEnum(SYS.rt_sigreturn)),
118 : "rcx", "r11", "memory"117 : "rcx", "r11", "memory"
119 ),118 ),
120 else => asm volatile (119 else => asm volatile (
121 \\ syscall120 \\ syscall
122 \\ retq
123 :121 :
124 : [number] "{rax}" (@intFromEnum(SYS.rt_sigreturn)),122 : [number] "{rax}" (@intFromEnum(SYS.rt_sigreturn)),
125 : "rcx", "r11", "memory"123 : "rcx", "r11", "memory"
126 ),124 ),
127 }125 }
128 unreachable;
129}126}
130127
131pub const mode_t = usize;128pub const mode_t = usize;
...@@ -400,92 +397,95 @@ fn gpRegisterOffset(comptime reg_index: comptime_int) usize {...@@ -400,92 +397,95 @@ fn gpRegisterOffset(comptime reg_index: comptime_int) usize {
400 return @offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "gregs") + @sizeOf(usize) * reg_index;397 return @offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "gregs") + @sizeOf(usize) * reg_index;
401}398}
402399
403fn getContextInternal() callconv(.Naked) void {400fn getContextInternal() callconv(.Naked) usize {
404 // TODO: Read GS/FS registers?401 // TODO: Read GS/FS registers?
405 asm volatile (402 asm volatile (
406 \\ movq $0, (%[flags_offset])(%%rdi)403 \\ movq $0, %[flags_offset:c](%%rdi)
407 \\ movq $0, (%[link_offset])(%%rdi)404 \\ movq $0, %[link_offset:c](%%rdi)
408 \\ movq %%r8, (%[r8_offset])(%%rdi)405 \\ movq %%r8, %[r8_offset:c](%%rdi)
409 \\ movq %%r9, (%[r9_offset])(%%rdi)406 \\ movq %%r9, %[r9_offset:c](%%rdi)
410 \\ movq %%r10, (%[r10_offset])(%%rdi)407 \\ movq %%r10, %[r10_offset:c](%%rdi)
411 \\ movq %%r11, (%[r11_offset])(%%rdi)408 \\ movq %%r11, %[r11_offset:c](%%rdi)
412 \\ movq %%r12, (%[r12_offset])(%%rdi)409 \\ movq %%r12, %[r12_offset:c](%%rdi)
413 \\ movq %%r13, (%[r13_offset])(%%rdi)410 \\ movq %%r13, %[r13_offset:c](%%rdi)
414 \\ movq %%r14, (%[r14_offset])(%%rdi)411 \\ movq %%r14, %[r14_offset:c](%%rdi)
415 \\ movq %%r15, (%[r15_offset])(%%rdi)412 \\ movq %%r15, %[r15_offset:c](%%rdi)
416 \\ movq %%rdi, (%[rdi_offset])(%%rdi)413 \\ movq %%rdi, %[rdi_offset:c](%%rdi)
417 \\ movq %%rsi, (%[rsi_offset])(%%rdi)414 \\ movq %%rsi, %[rsi_offset:c](%%rdi)
418 \\ movq %%rbp, (%[rbp_offset])(%%rdi)415 \\ movq %%rbp, %[rbp_offset:c](%%rdi)
419 \\ movq %%rbx, (%[rbx_offset])(%%rdi)416 \\ movq %%rbx, %[rbx_offset:c](%%rdi)
420 \\ movq %%rdx, (%[rdx_offset])(%%rdi)417 \\ movq %%rdx, %[rdx_offset:c](%%rdi)
421 \\ movq %%rax, (%[rax_offset])(%%rdi)418 \\ movq %%rax, %[rax_offset:c](%%rdi)
422 \\ movq %%rcx, (%[rcx_offset])(%%rdi)419 \\ movq %%rcx, %[rcx_offset:c](%%rdi)
423 \\ movq (%%rsp), %%rcx420 \\ movq (%%rsp), %%rcx
424 \\ movq %%rcx, (%[rip_offset])(%%rdi)421 \\ movq %%rcx, %[rip_offset:c](%%rdi)
425 \\ leaq 8(%%rsp), %%rcx422 \\ leaq 8(%%rsp), %%rcx
426 \\ movq %%rcx, (%[rsp_offset])(%%rdi)423 \\ movq %%rcx, %[rsp_offset:c](%%rdi)
427 \\ pushfq424 \\ pushfq
428 \\ popq (%[efl_offset])(%%rdi)425 \\ popq %[efl_offset:c](%%rdi)
429 \\ leaq (%[fpmem_offset])(%%rdi), %%rcx426 \\ leaq %[fpmem_offset:c](%%rdi), %%rcx
430 \\ movq %%rcx, (%[fpstate_offset])(%%rdi)427 \\ movq %%rcx, %[fpstate_offset:c](%%rdi)
431 \\ fnstenv (%%rcx)428 \\ fnstenv (%%rcx)
432 \\ fldenv (%%rcx)429 \\ fldenv (%%rcx)
433 \\ stmxcsr (%[mxcsr_offset])(%%rdi)430 \\ stmxcsr %[mxcsr_offset:c](%%rdi)
434 \\ leaq (%[stack_offset])(%%rdi), %%rsi431 \\ leaq %[stack_offset:c](%%rdi), %%rsi
435 \\ movq %%rdi, %%r8432 \\ movq %%rdi, %%r8
436 \\ xorq %%rdi, %%rdi433 \\ xorl %%edi, %%edi
437 \\ movq %[sigaltstack], %%rax434 \\ movq %[sigaltstack], %%rax
438 \\ syscall435 \\ syscall
439 \\ cmpq $0, %%rax436 \\ testq %%rax, %%rax
440 \\ jne return437 \\ jnz 0f
441 \\ movq %[sigprocmask], %%rax438 \\ movq %[sigprocmask], %%rax
442 \\ xorq %%rsi, %%rsi439 \\ xorl %%esi, %%esi
443 \\ leaq (%[sigmask_offset])(%%r8), %%rdx440 \\ leaq %[sigmask_offset:c](%%r8), %%rdx
444 \\ movq %[sigset_size], %%r10441 \\ movl %[sigset_size], %%r10d
445 \\ syscall442 \\ syscall
446 \\ return:443 \\0:
444 \\ retq
447 :445 :
448 : [flags_offset] "p" (@offsetOf(ucontext_t, "flags")),446 : [flags_offset] "i" (@offsetOf(ucontext_t, "flags")),
449 [link_offset] "p" (@offsetOf(ucontext_t, "link")),447 [link_offset] "i" (@offsetOf(ucontext_t, "link")),
450 [r8_offset] "p" (comptime gpRegisterOffset(REG.R8)),448 [r8_offset] "i" (comptime gpRegisterOffset(REG.R8)),
451 [r9_offset] "p" (comptime gpRegisterOffset(REG.R9)),449 [r9_offset] "i" (comptime gpRegisterOffset(REG.R9)),
452 [r10_offset] "p" (comptime gpRegisterOffset(REG.R10)),450 [r10_offset] "i" (comptime gpRegisterOffset(REG.R10)),
453 [r11_offset] "p" (comptime gpRegisterOffset(REG.R11)),451 [r11_offset] "i" (comptime gpRegisterOffset(REG.R11)),
454 [r12_offset] "p" (comptime gpRegisterOffset(REG.R12)),452 [r12_offset] "i" (comptime gpRegisterOffset(REG.R12)),
455 [r13_offset] "p" (comptime gpRegisterOffset(REG.R13)),453 [r13_offset] "i" (comptime gpRegisterOffset(REG.R13)),
456 [r14_offset] "p" (comptime gpRegisterOffset(REG.R14)),454 [r14_offset] "i" (comptime gpRegisterOffset(REG.R14)),
457 [r15_offset] "p" (comptime gpRegisterOffset(REG.R15)),455 [r15_offset] "i" (comptime gpRegisterOffset(REG.R15)),
458 [rdi_offset] "p" (comptime gpRegisterOffset(REG.RDI)),456 [rdi_offset] "i" (comptime gpRegisterOffset(REG.RDI)),
459 [rsi_offset] "p" (comptime gpRegisterOffset(REG.RSI)),457 [rsi_offset] "i" (comptime gpRegisterOffset(REG.RSI)),
460 [rbp_offset] "p" (comptime gpRegisterOffset(REG.RBP)),458 [rbp_offset] "i" (comptime gpRegisterOffset(REG.RBP)),
461 [rbx_offset] "p" (comptime gpRegisterOffset(REG.RBX)),459 [rbx_offset] "i" (comptime gpRegisterOffset(REG.RBX)),
462 [rdx_offset] "p" (comptime gpRegisterOffset(REG.RDX)),460 [rdx_offset] "i" (comptime gpRegisterOffset(REG.RDX)),
463 [rax_offset] "p" (comptime gpRegisterOffset(REG.RAX)),461 [rax_offset] "i" (comptime gpRegisterOffset(REG.RAX)),
464 [rcx_offset] "p" (comptime gpRegisterOffset(REG.RCX)),462 [rcx_offset] "i" (comptime gpRegisterOffset(REG.RCX)),
465 [rsp_offset] "p" (comptime gpRegisterOffset(REG.RSP)),463 [rsp_offset] "i" (comptime gpRegisterOffset(REG.RSP)),
466 [rip_offset] "p" (comptime gpRegisterOffset(REG.RIP)),464 [rip_offset] "i" (comptime gpRegisterOffset(REG.RIP)),
467 [efl_offset] "p" (comptime gpRegisterOffset(REG.EFL)),465 [efl_offset] "i" (comptime gpRegisterOffset(REG.EFL)),
468 [fpstate_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")),466 [fpstate_offset] "i" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")),
469 [fpmem_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem")),467 [fpmem_offset] "i" (@offsetOf(ucontext_t, "fpregs_mem")),
470 [mxcsr_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem") + @offsetOf(fpstate, "mxcsr")),468 [mxcsr_offset] "i" (@offsetOf(ucontext_t, "fpregs_mem") + @offsetOf(fpstate, "mxcsr")),
471 [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)),469 [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)),
472 [stack_offset] "p" (@offsetOf(ucontext_t, "stack")),470 [stack_offset] "i" (@offsetOf(ucontext_t, "stack")),
473 [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)),471 [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)),
474 [sigmask_offset] "p" (@offsetOf(ucontext_t, "sigmask")),472 [sigmask_offset] "i" (@offsetOf(ucontext_t, "sigmask")),
475 [sigset_size] "i" (linux.NSIG / 8),473 [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"
477 );475 );
478}476}
479477
480pub inline fn getcontext(context: *ucontext_t) usize {478pub inline fn getcontext(context: *ucontext_t) usize {
481 // This method is used so that getContextInternal can control479 // This method is used so that getContextInternal can control
482 // its prologue in order to read RSP from a constant offset480 // its prologue in order to read RSP from a constant offset
483 // The unused &getContextInternal input is required so the function is included in the binary.481 // An aligned stack is not needed for getContextInternal.
482 var clobber_rdi: usize = undefined;
484 return asm volatile (483 return asm volatile (
485 \\ call os.linux.x86_64.getContextInternal484 \\ callq %[getContextInternal:P]
486 : [ret] "={rax}" (-> usize),485 : [_] "={rax}" (-> usize),
487 : [context] "{rdi}" (context),486 [_] "={rdi}" (clobber_rdi),
487 : [_] "{rdi}" (context),
488 [getContextInternal] "X" (&getContextInternal),488 [getContextInternal] "X" (&getContextInternal),
489 : "memory", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11"489 : "cc", "memory", "rcx", "rdx", "rsi", "r8", "r10", "r11"
490 );490 );
491}491}
lib/std/start.zig+86-112
...@@ -101,7 +101,7 @@ fn main2() callconv(.C) c_int {...@@ -101,7 +101,7 @@ fn main2() callconv(.C) c_int {
101 return 0;101 return 0;
102}102}
103103
104fn _start2() callconv(.Naked) noreturn {104fn _start2() noreturn {
105 callMain2();105 callMain2();
106}106}
107107
...@@ -254,116 +254,92 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv...@@ -254,116 +254,92 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv
254}254}
255255
256fn _start() callconv(.Naked) noreturn {256fn _start() callconv(.Naked) noreturn {
257 switch (builtin.zig_backend) {257 asm volatile (switch (native_arch) {
258 .stage2_c => {258 .x86_64 =>
259 @export(argc_argv_ptr, .{ .name = "argc_argv_ptr" });259 \\ xorl %%ebp, %%ebp
260 @export(posixCallMainAndExit, .{ .name = "_posixCallMainAndExit" });260 \\ movq %%rsp, %[argc_argv_ptr]
261 switch (native_arch) {261 \\ andq $-16, %%rsp
262 .x86_64 => asm volatile (262 \\ callq %[posixCallMainAndExit:P]
263 \\ xorl %%ebp, %%ebp263 ,
264 \\ movq %%rsp, argc_argv_ptr264 .x86 =>
265 \\ andq $-16, %%rsp265 \\ xorl %%ebp, %%ebp
266 \\ call _posixCallMainAndExit266 \\ movl %%esp, %[argc_argv_ptr]
267 ),267 \\ andl $-16, %%esp
268 .x86 => asm volatile (268 \\ calll %[posixCallMainAndExit:P]
269 \\ xorl %%ebp, %%ebp269 ,
270 \\ movl %%esp, argc_argv_ptr270 .aarch64, .aarch64_be =>
271 \\ andl $-16, %%esp271 \\ mov fp, #0
272 \\ jmp _posixCallMainAndExit272 \\ mov lr, #0
273 ),273 \\ mov x0, sp
274 .aarch64, .aarch64_be => asm volatile (274 \\ str x0, %[argc_argv_ptr]
275 \\ mov fp, #0275 \\ b %[posixCallMainAndExit]
276 \\ mov lr, #0276 ,
277 \\ mov x0, sp277 .arm, .armeb, .thumb, .thumbeb =>
278 \\ adrp x1, argc_argv_ptr278 \\ mov fp, #0
279 \\ str x0, [x1, :lo12:argc_argv_ptr]279 \\ mov lr, #0
280 \\ b _posixCallMainAndExit280 \\ str sp, %[argc_argv_ptr]
281 ),281 \\ and sp, #-16
282 .arm, .armeb, .thumb => asm volatile (282 \\ b %[posixCallMainAndExit]
283 \\ mov fp, #0283 ,
284 \\ mov lr, #0284 .riscv64 =>
285 \\ str sp, argc_argv_ptr285 \\ li s0, 0
286 \\ and sp, #-16286 \\ li ra, 0
287 \\ b _posixCallMainAndExit287 \\ sd sp, %[argc_argv_ptr]
288 ),288 \\ andi sp, sp, -16
289 else => @compileError("unsupported arch"),289 \\ tail %[posixCallMainAndExit]@plt
290 }290 ,
291 unreachable;291 .mips, .mipsel =>
292 },292 // The lr is already zeroed on entry, as specified by the ABI.
293 else => switch (native_arch) {293 \\ addiu $fp, $zero, 0
294 .x86_64 => {294 \\ sw $sp, %[argc_argv_ptr]
295 argc_argv_ptr = asm volatile (295 \\ .set push
296 \\ xor %%ebp, %%ebp296 \\ .set noat
297 : [argc] "={rsp}" (-> [*]usize),297 \\ addiu $1, $zero, -16
298 );298 \\ and $sp, $sp, $1
299 },299 \\ .set pop
300 .x86 => {300 \\ j %[posixCallMainAndExit]
301 argc_argv_ptr = asm volatile (301 ,
302 \\ xor %%ebp, %%ebp302 .mips64, .mips64el =>
303 : [argc] "={esp}" (-> [*]usize),303 // The lr is already zeroed on entry, as specified by the ABI.
304 );304 \\ addiu $fp, $zero, 0
305 },305 \\ sd $sp, %[argc_argv_ptr]
306 .aarch64, .aarch64_be, .arm, .armeb, .thumb => {306 \\ .set push
307 argc_argv_ptr = asm volatile (307 \\ .set noat
308 \\ mov fp, #0308 \\ daddiu $1, $zero, -16
309 \\ mov lr, #0309 \\ and $sp, $sp, $1
310 : [argc] "={sp}" (-> [*]usize),310 \\ .set pop
311 );311 \\ j %[posixCallMainAndExit]
312 },312 ,
313 .riscv64 => {313 .powerpc, .powerpcle =>
314 argc_argv_ptr = asm volatile (314 // Setup the initial stack frame and clear the back chain pointer.
315 \\ li s0, 0315 \\ stw 1, %[argc_argv_ptr]
316 \\ li ra, 0316 \\ li 0, 0
317 : [argc] "={sp}" (-> [*]usize),317 \\ stwu 1, -16(1)
318 );318 \\ stw 0, 0(1)
319 },319 \\ mtlr 0
320 .mips, .mipsel, .mips64, .mips64el => {320 \\ b %[posixCallMainAndExit]
321 // The lr is already zeroed on entry, as specified by the ABI.321 ,
322 argc_argv_ptr = asm volatile (322 .powerpc64, .powerpc64le =>
323 \\ move $fp, $0323 // Setup the initial stack frame and clear the back chain pointer.
324 : [argc] "={sp}" (-> [*]usize),324 // TODO: Support powerpc64 (big endian) on ELFv2.
325 );325 \\ std 1, %[argc_argv_ptr]
326 },326 \\ li 0, 0
327 .powerpc => {327 \\ stdu 0, -32(1)
328 // Setup the initial stack frame and clear the back chain pointer.328 \\ mtlr 0
329 argc_argv_ptr = asm volatile (329 \\ b %[posixCallMainAndExit]
330 \\ mr 4, 1330 ,
331 \\ li 0, 0331 .sparc64 =>
332 \\ stwu 1,-16(1)332 // argc is stored after a register window (16 registers) plus stack bias
333 \\ stw 0, 0(1)333 \\ mov %%g0, %%i6
334 \\ mtlr 0334 \\ add %%o6, 2175, %%l0
335 : [argc] "={r4}" (-> [*]usize),335 \\ stx %%l0, %[argc_argv_ptr]
336 :336 \\ ba %[posixCallMainAndExit]
337 : "r0"337 ,
338 );
339 },
340 .powerpc64le => {
341 // Setup the initial stack frame and clear the back chain pointer.
342 // TODO: Support powerpc64 (big endian) on ELFv2.
343 argc_argv_ptr = asm volatile (
344 \\ mr 4, 1
345 \\ li 0, 0
346 \\ stdu 0, -32(1)
347 \\ mtlr 0
348 : [argc] "={r4}" (-> [*]usize),
349 :
350 : "r0"
351 );
352 },
353 .sparc64 => {
354 // argc is stored after a register window (16 registers) plus stack bias
355 argc_argv_ptr = asm (
356 \\ mov %%g0, %%i6
357 \\ add %%o6, 2175, %[argc]
358 : [argc] "=r" (-> [*]usize),
359 );
360 },
361 else => @compileError("unsupported arch"),338 else => @compileError("unsupported arch"),
362 },339 }
363 }340 : [argc_argv_ptr] "=m" (argc_argv_ptr),
364 // If LLVM inlines stack variables into _start, they will overwrite341 : [posixCallMainAndExit] "X" (&posixCallMainAndExit),
365 // the command line argument data.342 );
366 @call(.never_inline, posixCallMainAndExit, .{});
367}343}
368344
369fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {345fn WinStartup() callconv(std.os.windows.WINAPI) noreturn {
...@@ -390,8 +366,6 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {...@@ -390,8 +366,6 @@ fn wWinMainCRTStartup() callconv(std.os.windows.WINAPI) noreturn {
390}366}
391367
392fn posixCallMainAndExit() callconv(.C) noreturn {368fn posixCallMainAndExit() callconv(.C) noreturn {
393 @setAlignStack(16);
394
395 const argc = argc_argv_ptr[0];369 const argc = argc_argv_ptr[0];
396 const argv = @as([*][*:0]u8, @ptrCast(argc_argv_ptr + 1));370 const argv = @as([*][*:0]u8, @ptrCast(argc_argv_ptr + 1));
397371
lib/std/target.zig+5
...@@ -899,6 +899,10 @@ pub const Target = struct {...@@ -899,6 +899,10 @@ pub const Target = struct {
899 };899 };
900 }900 }
901901
902 pub fn isArmOrThumb(arch: Arch) bool {
903 return arch.isARM() or arch.isThumb();
904 }
905
902 pub fn isWasm(arch: Arch) bool {906 pub fn isWasm(arch: Arch) bool {
903 return switch (arch) {907 return switch (arch) {
904 .wasm32, .wasm64 => true,908 .wasm32, .wasm64 => true,
...@@ -1960,6 +1964,7 @@ pub const Target = struct {...@@ -1960,6 +1964,7 @@ pub const Target = struct {
1960 .thumbeb,1964 .thumbeb,
1961 => return if (target.os.tag.isDarwin() or target.os.tag == .windows) .signed else .unsigned,1965 => return if (target.os.tag.isDarwin() or target.os.tag == .windows) .signed else .unsigned,
1962 .powerpc, .powerpc64 => return if (target.os.tag.isDarwin()) .signed else .unsigned,1966 .powerpc, .powerpc64 => return if (target.os.tag.isDarwin()) .signed else .unsigned,
1967 .powerpcle,
1963 .powerpc64le,1968 .powerpc64le,
1964 .s390x,1969 .s390x,
1965 .xcore,1970 .xcore,
lib/zig.h+76-13
...@@ -1176,10 +1176,10 @@ typedef signed __int128 zig_i128;...@@ -1176,10 +1176,10 @@ typedef signed __int128 zig_i128;
11761176
1177#if zig_little_endian1177#if zig_little_endian
1178typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128;1178typedef 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;
1180#else1180#else
1181typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128;1181typedef 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;
1183#endif1183#endif
11841184
1185#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })1185#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,...@@ -3197,11 +3197,9 @@ zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64,
3197zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2)3197zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2)
3198zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2)3198zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2)
3199zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2)3199zig_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)
3201zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2)3200zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2)
3202zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2)3201zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2)
3203zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2)3202zig_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)
3205zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2)3203zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2)
3206zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2)3204zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2)
3207zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2)3205zig_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,...@@ -3213,6 +3211,21 @@ zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32,
3213zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2)3211zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2)
3214zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2)3212zig_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
3216#define zig_float_negate_builtin_0(w, c, sb) \3229#define zig_float_negate_builtin_0(w, c, sb) \
3217 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb))3230 zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb))
3218#define zig_float_negate_builtin_1(w, c, sb) -arg3231#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)))...@@ -3255,17 +3268,11 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
3255 return lhs operator rhs; \3268 return lhs operator rhs; \
3256 }3269 }
32573270
3258#define zig_float_builtins(w) \3271#define zig_common_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, ) \
3261 zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \3272 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, ) \
3263 zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \3273 zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \
3264 zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \3274 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, ) \
3267 zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \3275 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, ) \
3269 zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \3276 zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \
3270 zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \3277 zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \
3271 zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \3278 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)))...@@ -3309,12 +3316,68 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
3309 static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \3316 static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \
3310 return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \3317 return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \
3311 }3318 }
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, )
3312zig_float_builtins(16)3332zig_float_builtins(16)
3313zig_float_builtins(32)
3314zig_float_builtins(64)
3315zig_float_builtins(80)3333zig_float_builtins(80)
3316zig_float_builtins(128)3334zig_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
3318/* ============================ Atomics Support ============================= */3381/* ============================ Atomics Support ============================= */
33193382
3320/* Note that atomics should be implemented as macros because most3383/* 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 {...@@ -4186,6 +4186,7 @@ pub fn semaFile(mod: *Module, file: *File) SemaError!void {
4186 .owner_decl = new_decl,4186 .owner_decl = new_decl,
4187 .owner_decl_index = new_decl_index,4187 .owner_decl_index = new_decl_index,
4188 .func_index = .none,4188 .func_index = .none,
4189 .func_is_naked = false,
4189 .fn_ret_ty = Type.void,4190 .fn_ret_ty = Type.void,
4190 .fn_ret_ty_ies = null,4191 .fn_ret_ty_ies = null,
4191 .owner_func_index = .none,4192 .owner_func_index = .none,
...@@ -4268,6 +4269,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {...@@ -4268,6 +4269,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
4268 .owner_decl = decl,4269 .owner_decl = decl,
4269 .owner_decl_index = decl_index,4270 .owner_decl_index = decl_index,
4270 .func_index = .none,4271 .func_index = .none,
4272 .func_is_naked = false,
4271 .fn_ret_ty = Type.void,4273 .fn_ret_ty = Type.void,
4272 .fn_ret_ty_ies = null,4274 .fn_ret_ty_ies = null,
4273 .owner_func_index = .none,4275 .owner_func_index = .none,
...@@ -5213,6 +5215,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato...@@ -5213,6 +5215,7 @@ pub fn analyzeFnBody(mod: *Module, func_index: InternPool.Index, arena: Allocato
5213 .owner_decl = decl,5215 .owner_decl = decl,
5214 .owner_decl_index = decl_index,5216 .owner_decl_index = decl_index,
5215 .func_index = func_index,5217 .func_index = func_index,
5218 .func_is_naked = fn_ty_info.cc == .Naked,
5216 .fn_ret_ty = fn_ty_info.return_type.toType(),5219 .fn_ret_ty = fn_ty_info.return_type.toType(),
5217 .fn_ret_ty_ies = null,5220 .fn_ret_ty_ies = null,
5218 .owner_func_index = func_index,5221 .owner_func_index = func_index,
src/Sema.zig+28-3
...@@ -30,6 +30,8 @@ owner_func_index: InternPool.Index,...@@ -30,6 +30,8 @@ owner_func_index: InternPool.Index,
30/// an inline or comptime function call.30/// an inline or comptime function call.
31/// This could be `none`, a `func_decl`, or a `func_instance`.31/// This could be `none`, a `func_decl`, or a `func_instance`.
32func_index: InternPool.Index,32func_index: InternPool.Index,
33/// Whether the type of func_index has a calling convention of `.Naked`.
34func_is_naked: bool,
33/// Used to restore the error return trace when returning a non-error from a function.35/// Used to restore the error return trace when returning a non-error from a function.
34error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,36error_return_trace_index_on_fn_entry: Air.Inst.Ref = .none,
35/// When semantic analysis needs to know the return type of the function whose body37/// When semantic analysis needs to know the return type of the function whose body
...@@ -6827,6 +6829,10 @@ fn analyzeCall(...@@ -6827,6 +6829,10 @@ fn analyzeCall(
6827 var is_inline_call = is_comptime_call or modifier == .always_inline or6829 var is_inline_call = is_comptime_call or modifier == .always_inline or
6828 func_ty_info.cc == .Inline;6830 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
6830 if (!is_inline_call and is_generic_call) {6836 if (!is_inline_call and is_generic_call) {
6831 if (sema.instantiateGenericCall(6837 if (sema.instantiateGenericCall(
6832 block,6838 block,
...@@ -7509,6 +7515,9 @@ fn instantiateGenericCall(...@@ -7509,6 +7515,9 @@ fn instantiateGenericCall(
7509 .owner_decl = sema.owner_decl,7515 .owner_decl = sema.owner_decl,
7510 .owner_decl_index = sema.owner_decl_index,7516 .owner_decl_index = sema.owner_decl_index,
7511 .func_index = sema.owner_func_index,7517 .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,
7512 .fn_ret_ty = Type.void,7521 .fn_ret_ty = Type.void,
7513 .fn_ret_ty_ies = null,7522 .fn_ret_ty_ies = null,
7514 .owner_func_index = .none,7523 .owner_func_index = .none,
...@@ -18193,10 +18202,20 @@ fn zirRetImplicit(...@@ -18193,10 +18202,20 @@ fn zirRetImplicit(
18193 const tracy = trace(@src());18202 const tracy = trace(@src());
18194 defer tracy.end();18203 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
18196 const mod = sema.mod;18216 const mod = sema.mod;
18197 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;18217 const inst_data = sema.code.instructions.items(.data)[inst].un_tok;
18198 const operand = try sema.resolveInst(inst_data.operand);18218 const operand = try sema.resolveInst(inst_data.operand);
18199
18200 const r_brace_src = inst_data.src();18219 const r_brace_src = inst_data.src();
18201 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };18220 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = 0 };
18202 const base_tag = sema.fn_ret_ty.baseZigTypeTag(mod);18221 const base_tag = sema.fn_ret_ty.baseZigTypeTag(mod);
...@@ -18222,7 +18241,7 @@ fn zirRetImplicit(...@@ -18222,7 +18241,7 @@ fn zirRetImplicit(
18222 return sema.failWithOwnedErrorMsg(msg);18241 return sema.failWithOwnedErrorMsg(msg);
18223 }18242 }
1822418243
18225 return sema.analyzeRet(block, operand, .unneeded);18244 return sema.analyzeRet(block, operand, r_brace_src);
18226}18245}
1822718246
18228fn zirRetNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir.Inst.Index {18247fn 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...@@ -18244,7 +18263,7 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir
18244 const src = inst_data.src();18263 const src = inst_data.src();
18245 const ret_ptr = try sema.resolveInst(inst_data.operand);18264 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) {
18248 const operand = try sema.analyzeLoad(block, src, ret_ptr, src);18267 const operand = try sema.analyzeLoad(block, src, ret_ptr, src);
18249 return sema.analyzeRet(block, operand, src);18268 return sema.analyzeRet(block, operand, src);
18250 }18269 }
...@@ -18450,6 +18469,8 @@ fn analyzeRet(...@@ -18450,6 +18469,8 @@ fn analyzeRet(
18450 return always_noreturn;18469 return always_noreturn;
18451 } else if (block.is_comptime) {18470 } else if (block.is_comptime) {
18452 return sema.fail(block, src, "function called at runtime cannot return value at comptime", .{});18471 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", .{});
18453 }18474 }
1845418475
18455 try sema.resolveTypeLayout(sema.fn_ret_ty);18476 try sema.resolveTypeLayout(sema.fn_ret_ty);
...@@ -33571,6 +33592,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -33571,6 +33592,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
33571 .owner_decl = decl,33592 .owner_decl = decl,
33572 .owner_decl_index = decl_index,33593 .owner_decl_index = decl_index,
33573 .func_index = .none,33594 .func_index = .none,
33595 .func_is_naked = false,
33574 .fn_ret_ty = Type.void,33596 .fn_ret_ty = Type.void,
33575 .fn_ret_ty_ies = null,33597 .fn_ret_ty_ies = null,
33576 .owner_func_index = .none,33598 .owner_func_index = .none,
...@@ -33622,6 +33644,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi...@@ -33622,6 +33644,7 @@ fn semaBackingIntType(mod: *Module, struct_obj: *Module.Struct) CompileError!voi
33622 .owner_decl = decl,33644 .owner_decl = decl,
33623 .owner_decl_index = decl_index,33645 .owner_decl_index = decl_index,
33624 .func_index = .none,33646 .func_index = .none,
33647 .func_is_naked = false,
33625 .fn_ret_ty = Type.void,33648 .fn_ret_ty = Type.void,
33626 .fn_ret_ty_ies = null,33649 .fn_ret_ty_ies = null,
33627 .owner_func_index = .none,33650 .owner_func_index = .none,
...@@ -34405,6 +34428,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void...@@ -34405,6 +34428,7 @@ fn semaStructFields(mod: *Module, struct_obj: *Module.Struct) CompileError!void
34405 .owner_decl = decl,34428 .owner_decl = decl,
34406 .owner_decl_index = decl_index,34429 .owner_decl_index = decl_index,
34407 .func_index = .none,34430 .func_index = .none,
34431 .func_is_naked = false,
34408 .fn_ret_ty = Type.void,34432 .fn_ret_ty = Type.void,
34409 .fn_ret_ty_ies = null,34433 .fn_ret_ty_ies = null,
34410 .owner_func_index = .none,34434 .owner_func_index = .none,
...@@ -34748,6 +34772,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {...@@ -34748,6 +34772,7 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
34748 .owner_decl = decl,34772 .owner_decl = decl,
34749 .owner_decl_index = decl_index,34773 .owner_decl_index = decl_index,
34750 .func_index = .none,34774 .func_index = .none,
34775 .func_is_naked = false,
34751 .fn_ret_ty = Type.void,34776 .fn_ret_ty = Type.void,
34752 .fn_ret_ty_ies = null,34777 .fn_ret_ty_ies = null,
34753 .owner_func_index = .none,34778 .owner_func_index = .none,
src/TypedValue.zig+1
...@@ -196,6 +196,7 @@ pub fn print(...@@ -196,6 +196,7 @@ pub fn print(
196 .undef => return writer.writeAll("undefined"),196 .undef => return writer.writeAll("undefined"),
197 .runtime_value => return writer.writeAll("(runtime value)"),197 .runtime_value => return writer.writeAll("(runtime value)"),
198 .simple_value => |simple_value| switch (simple_value) {198 .simple_value => |simple_value| switch (simple_value) {
199 .void => return writer.writeAll("{}"),
199 .empty_struct => return printAggregate(ty, val, writer, level, mod),200 .empty_struct => return printAggregate(ty, val, writer, level, mod),
200 .generic_poison => return writer.writeAll("(generic poison)"),201 .generic_poison => return writer.writeAll("(generic poison)"),
201 else => return writer.writeAll(@tagName(simple_value)),202 else => return writer.writeAll(@tagName(simple_value)),
src/arch/x86_64/CodeGen.zig+155-54
...@@ -177,7 +177,7 @@ pub const MCValue = union(enum) {...@@ -177,7 +177,7 @@ pub const MCValue = union(enum) {
177 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.177 /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register.
178 register_overflow: struct { reg: Register, eflags: Condition },178 register_overflow: struct { reg: Register, eflags: Condition },
179 /// The value is in memory at a hard-coded address.179 /// The value is in memory at a hard-coded address.
180 /// If the type is a pointer, it means the pointer address is at this memory location.180 /// If the type is a pointer, it means the pointer address is stored at this memory location.
181 memory: u64,181 memory: u64,
182 /// The value is in memory at a constant offset from the address in a register.182 /// The value is in memory at a constant offset from the address in a register.
183 indirect: RegisterOffset,183 indirect: RegisterOffset,
...@@ -300,7 +300,7 @@ pub const MCValue = union(enum) {...@@ -300,7 +300,7 @@ pub const MCValue = union(enum) {
300 .load_tlv,300 .load_tlv,
301 .load_frame,301 .load_frame,
302 .reserved_frame,302 .reserved_frame,
303 => unreachable, // not a dereferenceable303 => unreachable, // not dereferenceable
304 .immediate => |addr| .{ .memory = addr },304 .immediate => |addr| .{ .memory = addr },
305 .register => |reg| .{ .indirect = .{ .reg = reg } },305 .register => |reg| .{ .indirect = .{ .reg = reg } },
306 .register_offset => |reg_off| .{ .indirect = reg_off },306 .register_offset => |reg_off| .{ .indirect = reg_off },
...@@ -3468,14 +3468,14 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa...@@ -3468,14 +3468,14 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
3468 const mod = self.bin_file.options.module.?;3468 const mod = self.bin_file.options.module.?;
3469 const abi_size: u32 = @intCast(ty.abiSize(mod));3469 const abi_size: u32 = @intCast(ty.abiSize(mod));
3470 const int_info = ty.intInfo(mod);3470 const int_info = ty.intInfo(mod);
3471 const dividend: Register = switch (lhs) {3471 const dividend = switch (lhs) {
3472 .register => |reg| reg,3472 .register => |reg| reg,
3473 else => try self.copyToTmpRegister(ty, lhs),3473 else => try self.copyToTmpRegister(ty, lhs),
3474 };3474 };
3475 const dividend_lock = self.register_manager.lockReg(dividend);3475 const dividend_lock = self.register_manager.lockReg(dividend);
3476 defer if (dividend_lock) |lock| self.register_manager.unlockReg(lock);3476 defer if (dividend_lock) |lock| self.register_manager.unlockReg(lock);
34773477
3478 const divisor: Register = switch (rhs) {3478 const divisor = switch (rhs) {
3479 .register => |reg| reg,3479 .register => |reg| reg,
3480 else => try self.copyToTmpRegister(ty, rhs),3480 else => try self.copyToTmpRegister(ty, rhs),
3481 };3481 };
...@@ -9184,6 +9184,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -9184,6 +9184,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void {
9184}9184}
91859185
9186fn airAsm(self: *Self, inst: Air.Inst.Index) !void {9186fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9187 const mod = self.bin_file.options.module.?;
9187 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;9188 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
9188 const extra = self.air.extraData(Air.Asm, ty_pl.payload);9189 const extra = self.air.extraData(Air.Asm, ty_pl.payload);
9189 const clobbers_len: u31 = @truncate(extra.data.flags);9190 const clobbers_len: u31 = @truncate(extra.data.flags);
...@@ -9196,23 +9197,15 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9196,23 +9197,15 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
91969197
9197 var result: MCValue = .none;9198 var result: MCValue = .none;
9198 var args = std.StringArrayHashMap(MCValue).init(self.gpa);9199 var args = std.StringArrayHashMap(MCValue).init(self.gpa);
9199 try args.ensureTotalCapacity(outputs.len + inputs.len + clobbers_len);9200 try args.ensureTotalCapacity(outputs.len + inputs.len);
9200 defer {9201 defer {
9201 for (args.values()) |arg| switch (arg) {9202 for (args.values()) |arg| if (arg.getReg()) |reg|
9202 .register => |reg| self.register_manager.unlockReg(.{ .register = reg }),9203 self.register_manager.unlockReg(.{ .register = reg });
9203 else => {},
9204 };
9205 args.deinit();9204 args.deinit();
9206 }9205 }
92079206
9208 if (outputs.len > 1) {9207 var outputs_extra_i = extra_i;
9209 return self.fail("TODO implement codegen for asm with more than 1 output", .{});
9210 }
9211
9212 for (outputs) |output| {9208 for (outputs) |output| {
9213 if (output != .none) {
9214 return self.fail("TODO implement codegen for non-expr asm", .{});
9215 }
9216 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);9209 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]);
9217 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);9210 const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0);
9218 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);9211 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
...@@ -9220,21 +9213,48 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9220,21 +9213,48 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9220 // for the string, we still use the next u32 for the null terminator.9213 // for the string, we still use the next u32 for the null terminator.
9221 extra_i += (constraint.len + name.len + (2 + 3)) / 4;9214 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
92229215
9223 const mcv: MCValue = if (mem.eql(u8, constraint, "=r"))9216 const maybe_inst = switch (output) {
9224 .{ .register = self.register_manager.tryAllocReg(inst, gp) orelse9217 .none => inst,
9225 return self.fail("ran out of registers lowering inline asm", .{}) }9218 else => null,
9219 };
9220 const ty = switch (output) {
9221 .none => self.typeOfIndex(inst),
9222 else => self.typeOf(output).childType(mod),
9223 };
9224 const arg_maybe_reg: ?Register = if (mem.eql(u8, constraint, "=r"))
9225 self.register_manager.tryAllocReg(maybe_inst, regClassForType(ty, mod)) orelse
9226 return self.fail("ran out of registers lowering inline asm", .{})
9227 else if (mem.eql(u8, constraint, "=m"))
9228 if (output != .none) null else return self.fail(
9229 "memory constraint unsupported for asm result",
9230 .{},
9231 )
9232 else if (mem.eql(u8, constraint, "=g"))
9233 self.register_manager.tryAllocReg(maybe_inst, regClassForType(ty, mod)) orelse
9234 if (output != .none) null else return self.fail(
9235 "ran out of register lowering inline asm",
9236 .{},
9237 )
9226 else if (mem.startsWith(u8, constraint, "={") and mem.endsWith(u8, constraint, "}"))9238 else if (mem.startsWith(u8, constraint, "={") and mem.endsWith(u8, constraint, "}"))
9227 .{ .register = parseRegName(constraint["={".len .. constraint.len - "}".len]) orelse9239 parseRegName(constraint["={".len .. constraint.len - "}".len]) orelse
9228 return self.fail("unrecognized register constraint: '{s}'", .{constraint}) }9240 return self.fail("invalid register constraint: '{s}'", .{constraint})
9229 else9241 else
9230 return self.fail("unrecognized constraint: '{s}'", .{constraint});9242 return self.fail("invalid constraint: '{s}'", .{constraint});
9231 args.putAssumeCapacity(name, mcv);9243 const arg_mcv: MCValue = if (arg_maybe_reg) |reg| .{ .register = reg } else arg: {
9232 switch (mcv) {9244 const ptr_mcv = try self.resolveInst(output);
9233 .register => |reg| _ = if (RegisterManager.indexOfRegIntoTracked(reg)) |_|9245 switch (ptr_mcv) {
9234 self.register_manager.lockRegAssumeUnused(reg),9246 .immediate => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
9235 else => {},9247 break :arg ptr_mcv.deref(),
9236 }9248 .register, .register_offset, .lea_frame => break :arg ptr_mcv.deref(),
9237 if (output == .none) result = mcv;9249 else => {},
9250 }
9251 break :arg .{ .indirect = .{ .reg = try self.copyToTmpRegister(Type.usize, ptr_mcv) } };
9252 };
9253 if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {
9254 _ = self.register_manager.lockRegAssumeUnused(reg);
9255 };
9256 args.putAssumeCapacity(name, arg_mcv);
9257 if (output == .none) result = arg_mcv;
9238 }9258 }
92399259
9240 for (inputs) |input| {9260 for (inputs) |input| {
...@@ -9245,16 +9265,53 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9245,16 +9265,53 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9245 // for the string, we still use the next u32 for the null terminator.9265 // for the string, we still use the next u32 for the null terminator.
9246 extra_i += (constraint.len + name.len + (2 + 3)) / 4;9266 extra_i += (constraint.len + name.len + (2 + 3)) / 4;
92479267
9248 if (constraint.len < 3 or constraint[0] != '{' or constraint[constraint.len - 1] != '}') {9268 const ty = self.typeOf(input);
9249 return self.fail("unrecognized asm input constraint: '{s}'", .{constraint});9269 const input_mcv = try self.resolveInst(input);
9250 }9270 const arg_mcv: MCValue = if (mem.eql(u8, constraint, "r")) switch (input_mcv) {
9251 const reg_name = constraint[1 .. constraint.len - 1];9271 .register => input_mcv,
9252 const reg = parseRegName(reg_name) orelse9272 else => .{ .register = try self.copyToTmpRegister(ty, input_mcv) },
9253 return self.fail("unrecognized register: '{s}'", .{reg_name});9273 } else if (mem.eql(u8, constraint, "m")) arg: {
92549274 switch (input_mcv) {
9255 const arg_mcv = try self.resolveInst(input);9275 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
9256 try self.register_manager.getReg(reg, null);9276 break :arg input_mcv,
9257 try self.genSetReg(reg, self.typeOf(input), arg_mcv);9277 .indirect, .load_frame => break :arg input_mcv,
9278 .load_direct, .load_got, .load_tlv => {},
9279 else => {
9280 const temp_mcv = try self.allocTempRegOrMem(ty, false);
9281 try self.genCopy(ty, temp_mcv, input_mcv);
9282 break :arg temp_mcv;
9283 },
9284 }
9285 const addr_reg = self.register_manager.tryAllocReg(null, gp) orelse {
9286 const temp_mcv = try self.allocTempRegOrMem(ty, false);
9287 try self.genCopy(ty, temp_mcv, input_mcv);
9288 break :arg temp_mcv;
9289 };
9290 try self.genSetReg(addr_reg, Type.usize, input_mcv.address());
9291 break :arg .{ .indirect = .{ .reg = addr_reg } };
9292 } else if (mem.eql(u8, constraint, "g")) arg: {
9293 switch (input_mcv) {
9294 .register, .indirect, .load_frame => break :arg input_mcv,
9295 .memory => |addr| if (math.cast(i32, @as(i64, @bitCast(addr)))) |_|
9296 break :arg input_mcv,
9297 else => {},
9298 }
9299 const temp_mcv = try self.allocTempRegOrMem(ty, true);
9300 try self.genCopy(ty, temp_mcv, input_mcv);
9301 break :arg temp_mcv;
9302 } else if (mem.eql(u8, constraint, "X"))
9303 input_mcv
9304 else if (mem.startsWith(u8, constraint, "{") and mem.endsWith(u8, constraint, "}")) arg: {
9305 const reg = parseRegName(constraint["{".len .. constraint.len - "}".len]) orelse
9306 return self.fail("invalid register constraint: '{s}'", .{constraint});
9307 try self.register_manager.getReg(reg, null);
9308 try self.genSetReg(reg, ty, input_mcv);
9309 break :arg .{ .register = reg };
9310 } else return self.fail("invalid constraint: '{s}'", .{constraint});
9311 if (arg_mcv.getReg()) |reg| if (RegisterManager.indexOfRegIntoTracked(reg)) |_| {
9312 _ = self.register_manager.lockReg(reg);
9313 };
9314 args.putAssumeCapacity(name, arg_mcv);
9258 }9315 }
92599316
9260 {9317 {
...@@ -9293,7 +9350,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9293,7 +9350,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9293 }9350 }
9294 }9351 }
9295 break :mnem std.meta.stringToEnum(Mir.Inst.Tag, mnem_str) orelse9352 break :mnem std.meta.stringToEnum(Mir.Inst.Tag, mnem_str) orelse
9296 return self.fail("Invalid mnemonic: '{s}'", .{mnem_str});9353 return self.fail("invalid mnemonic: '{s}'", .{mnem_str});
9297 } };9354 } };
92989355
9299 var op_it = mem.tokenizeScalar(u8, mnem_it.rest(), ',');9356 var op_it = mem.tokenizeScalar(u8, mnem_it.rest(), ',');
...@@ -9304,43 +9361,73 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9304,43 +9361,73 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9304 if (mem.startsWith(u8, op_str, "%%")) {9361 if (mem.startsWith(u8, op_str, "%%")) {
9305 const colon = mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');9362 const colon = mem.indexOfScalarPos(u8, op_str, "%%".len + 2, ':');
9306 const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse9363 const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse
9307 return self.fail("Invalid register: '{s}'", .{op_str});9364 return self.fail("invalid register: '{s}'", .{op_str});
9308 if (colon) |colon_pos| {9365 if (colon) |colon_pos| {
9309 const disp = std.fmt.parseInt(i32, op_str[colon_pos + 1 ..], 0) catch9366 const disp = std.fmt.parseInt(i32, op_str[colon_pos + 1 ..], 0) catch
9310 return self.fail("Invalid displacement: '{s}'", .{op_str});9367 return self.fail("invalid displacement: '{s}'", .{op_str});
9311 op.* = .{ .mem = Memory.sib(9368 op.* = .{ .mem = Memory.sib(
9312 mnem_size orelse return self.fail("Unknown size: '{s}'", .{op_str}),9369 mnem_size orelse return self.fail("unknown size: '{s}'", .{op_str}),
9313 .{ .base = .{ .reg = reg }, .disp = disp },9370 .{ .base = .{ .reg = reg }, .disp = disp },
9314 ) };9371 ) };
9315 } else {9372 } else {
9316 if (mnem_size) |size| if (reg.bitSize() != size.bitSize())9373 if (mnem_size) |size| if (reg.bitSize() != size.bitSize())
9317 return self.fail("Invalid register size: '{s}'", .{op_str});9374 return self.fail("invalid register size: '{s}'", .{op_str});
9318 op.* = .{ .reg = reg };9375 op.* = .{ .reg = reg };
9319 }9376 }
9320 } else if (mem.startsWith(u8, op_str, "%[") and mem.endsWith(u8, op_str, "]")) {9377 } else if (mem.startsWith(u8, op_str, "%[") and mem.endsWith(u8, op_str, "]")) {
9321 switch (args.get(op_str["%[".len .. op_str.len - "]".len]) orelse9378 const colon = mem.indexOfScalarPos(u8, op_str, "%[".len, ':');
9322 return self.fail("No matching constraint: '{s}'", .{op_str})) {9379 const modifier = if (colon) |colon_pos|
9323 .register => |reg| op.* = .{ .reg = reg },9380 op_str[colon_pos + 1 .. op_str.len - "]".len]
9324 else => return self.fail("Invalid constraint: '{s}'", .{op_str}),9381 else
9325 }9382 "";
9383 op.* = switch (args.get(op_str["%[".len .. colon orelse op_str.len - "]".len]) orelse
9384 return self.fail("no matching constraint: '{s}'", .{op_str})) {
9385 .register => |reg| if (std.mem.eql(u8, modifier, ""))
9386 .{ .reg = reg }
9387 else
9388 return self.fail("invalid modifier: '{s}'", .{modifier}),
9389 .memory => |addr| if (std.mem.eql(u8, modifier, "") or
9390 std.mem.eql(u8, modifier, "P"))
9391 .{ .mem = Memory.sib(
9392 mnem_size orelse return self.fail("unknown size: '{s}'", .{op_str}),
9393 .{ .base = .{ .reg = .ds }, .disp = @intCast(@as(i64, @bitCast(addr))) },
9394 ) }
9395 else
9396 return self.fail("invalid modifier: '{s}'", .{modifier}),
9397 .indirect => |reg_off| if (std.mem.eql(u8, modifier, ""))
9398 .{ .mem = Memory.sib(
9399 mnem_size orelse return self.fail("unknown size: '{s}'", .{op_str}),
9400 .{ .base = .{ .reg = reg_off.reg }, .disp = reg_off.off },
9401 ) }
9402 else
9403 return self.fail("invalid modifier: '{s}'", .{modifier}),
9404 .load_frame => |frame_addr| if (std.mem.eql(u8, modifier, ""))
9405 .{ .mem = Memory.sib(
9406 mnem_size orelse return self.fail("unknown size: '{s}'", .{op_str}),
9407 .{ .base = .{ .frame = frame_addr.index }, .disp = frame_addr.off },
9408 ) }
9409 else
9410 return self.fail("invalid modifier: '{s}'", .{modifier}),
9411 else => return self.fail("invalid constraint: '{s}'", .{op_str}),
9412 };
9326 } else if (mem.startsWith(u8, op_str, "$")) {9413 } else if (mem.startsWith(u8, op_str, "$")) {
9327 if (std.fmt.parseInt(i32, op_str["$".len..], 0)) |s| {9414 if (std.fmt.parseInt(i32, op_str["$".len..], 0)) |s| {
9328 if (mnem_size) |size| {9415 if (mnem_size) |size| {
9329 const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - (size.bitSize() - 1));9416 const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - (size.bitSize() - 1));
9330 if ((if (s < 0) ~s else s) > max)9417 if ((if (s < 0) ~s else s) > max)
9331 return self.fail("Invalid immediate size: '{s}'", .{op_str});9418 return self.fail("invalid immediate size: '{s}'", .{op_str});
9332 }9419 }
9333 op.* = .{ .imm = Immediate.s(s) };9420 op.* = .{ .imm = Immediate.s(s) };
9334 } else |_| if (std.fmt.parseInt(u64, op_str["$".len..], 0)) |u| {9421 } else |_| if (std.fmt.parseInt(u64, op_str["$".len..], 0)) |u| {
9335 if (mnem_size) |size| {9422 if (mnem_size) |size| {
9336 const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - size.bitSize());9423 const max = @as(u64, math.maxInt(u64)) >> @intCast(64 - size.bitSize());
9337 if (u > max)9424 if (u > max)
9338 return self.fail("Invalid immediate size: '{s}'", .{op_str});9425 return self.fail("invalid immediate size: '{s}'", .{op_str});
9339 }9426 }
9340 op.* = .{ .imm = Immediate.u(u) };9427 op.* = .{ .imm = Immediate.u(u) };
9341 } else |_| return self.fail("Invalid immediate: '{s}'", .{op_str});9428 } else |_| return self.fail("invalid immediate: '{s}'", .{op_str});
9342 } else return self.fail("Invalid operand: '{s}'", .{op_str});9429 } else return self.fail("invalid operand: '{s}'", .{op_str});
9343 } else if (op_it.next()) |op_str| return self.fail("Extra operand: '{s}'", .{op_str});9430 } else if (op_it.next()) |op_str| return self.fail("extra operand: '{s}'", .{op_str});
93449431
9345 (switch (ops[0]) {9432 (switch (ops[0]) {
9346 .none => self.asmOpOnly(mnem_tag),9433 .none => self.asmOpOnly(mnem_tag),
...@@ -9407,6 +9494,20 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {...@@ -9407,6 +9494,20 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void {
9407 };9494 };
9408 }9495 }
94099496
9497 for (outputs, args.values()[0..outputs.len]) |output, mcv| {
9498 const extra_bytes = std.mem.sliceAsBytes(self.air.extra[outputs_extra_i..]);
9499 const constraint =
9500 std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[outputs_extra_i..]), 0);
9501 const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0);
9502 // This equation accounts for the fact that even if we have exactly 4 bytes
9503 // for the string, we still use the next u32 for the null terminator.
9504 outputs_extra_i += (constraint.len + name.len + (2 + 3)) / 4;
9505
9506 if (output == .none) continue;
9507 if (mcv != .register) continue;
9508 try self.store(self.typeOf(output), try self.resolveInst(output), mcv);
9509 }
9510
9410 simple: {9511 simple: {
9411 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);9512 var buf = [1]Air.Inst.Ref{.none} ** (Liveness.bpi - 1);
9412 var buf_index: usize = 0;9513 var buf_index: usize = 0;
src/codegen/c.zig+52-35
...@@ -30,7 +30,7 @@ pub const CValue = union(enum) {...@@ -30,7 +30,7 @@ pub const CValue = union(enum) {
30 /// Address of a local.30 /// Address of a local.
31 local_ref: LocalIndex,31 local_ref: LocalIndex,
32 /// A constant instruction, to be rendered inline.32 /// A constant instruction, to be rendered inline.
33 constant: Air.Inst.Ref,33 constant: InternPool.Index,
34 /// Index into the parameters34 /// Index into the parameters
35 arg: usize,35 arg: usize,
36 /// The array field of a parameter36 /// The array field of a parameter
...@@ -302,7 +302,7 @@ pub const Function = struct {...@@ -302,7 +302,7 @@ pub const Function = struct {
302 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);302 try f.object.dg.renderValue(writer, ty, val, .StaticInitializer);
303 try writer.writeAll(";\n ");303 try writer.writeAll(";\n ");
304 break :result decl_c_value;304 break :result decl_c_value;
305 } else .{ .constant = ref };305 } else .{ .constant = val.toIntern() };
306306
307 gop.value_ptr.* = result;307 gop.value_ptr.* = result;
308 return result;308 return result;
...@@ -352,57 +352,63 @@ pub const Function = struct {...@@ -352,57 +352,63 @@ pub const Function = struct {
352352
353 fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void {353 fn writeCValue(f: *Function, w: anytype, c_value: CValue, location: ValueRenderLocation) !void {
354 switch (c_value) {354 switch (c_value) {
355 .constant => |inst| {355 .constant => |val| try f.object.dg.renderValue(
356 const mod = f.object.dg.module;356 w,
357 const ty = f.typeOf(inst);357 f.object.dg.module.intern_pool.typeOf(val).toType(),
358 const val = (try f.air.value(inst, mod)).?;358 val.toValue(),
359 return f.object.dg.renderValue(w, ty, val, location);359 location,
360 },360 ),
361 .undef => |ty| return f.object.dg.renderValue(w, ty, Value.undef, location),361 .undef => |ty| try f.object.dg.renderValue(w, ty, Value.undef, location),
362 else => return f.object.dg.writeCValue(w, c_value),362 else => try f.object.dg.writeCValue(w, c_value),
363 }363 }
364 }364 }
365365
366 fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void {366 fn writeCValueDeref(f: *Function, w: anytype, c_value: CValue) !void {
367 switch (c_value) {367 switch (c_value) {
368 .constant => |inst| {368 .constant => |val| {
369 const mod = f.object.dg.module;
370 const ty = f.typeOf(inst);
371 const val = (try f.air.value(inst, mod)).?;
372 try w.writeAll("(*");369 try w.writeAll("(*");
373 try f.object.dg.renderValue(w, ty, val, .Other);370 try f.object.dg.renderValue(
374 return w.writeByte(')');371 w,
372 f.object.dg.module.intern_pool.typeOf(val).toType(),
373 val.toValue(),
374 .Other,
375 );
376 try w.writeByte(')');
375 },377 },
376 else => return f.object.dg.writeCValueDeref(w, c_value),378 else => try f.object.dg.writeCValueDeref(w, c_value),
377 }379 }
378 }380 }
379381
380 fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {382 fn writeCValueMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
381 switch (c_value) {383 switch (c_value) {
382 .constant => |inst| {384 .constant => |val| {
383 const mod = f.object.dg.module;385 try f.object.dg.renderValue(
384 const ty = f.typeOf(inst);386 w,
385 const val = (try f.air.value(inst, mod)).?;387 f.object.dg.module.intern_pool.typeOf(val).toType(),
386 try f.object.dg.renderValue(w, ty, val, .Other);388 val.toValue(),
389 .Other,
390 );
387 try w.writeByte('.');391 try w.writeByte('.');
388 return f.writeCValue(w, member, .Other);392 try f.writeCValue(w, member, .Other);
389 },393 },
390 else => return f.object.dg.writeCValueMember(w, c_value, member),394 else => try f.object.dg.writeCValueMember(w, c_value, member),
391 }395 }
392 }396 }
393397
394 fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {398 fn writeCValueDerefMember(f: *Function, w: anytype, c_value: CValue, member: CValue) !void {
395 switch (c_value) {399 switch (c_value) {
396 .constant => |inst| {400 .constant => |val| {
397 const mod = f.object.dg.module;
398 const ty = f.typeOf(inst);
399 const val = (try f.air.value(inst, mod)).?;
400 try w.writeByte('(');401 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 );
402 try w.writeAll(")->");408 try w.writeAll(")->");
403 return f.writeCValue(w, member, .Other);409 try f.writeCValue(w, member, .Other);
404 },410 },
405 else => return f.object.dg.writeCValueDerefMember(w, c_value, member),411 else => try f.object.dg.writeCValueDerefMember(w, c_value, member),
406 }412 }
407 }413 }
408414
...@@ -4763,11 +4769,22 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4763,11 +4769,22 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue {
4763 return .none;4769 return .none;
4764}4770}
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();
4767 return switch (constraint[0]) {4774 return switch (constraint[0]) {
4768 '{' => true,4775 '{' => true,
4769 'i', 'r' => false,4776 '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 },
4771 };4788 };
4772}4789}
47734790
...@@ -4848,7 +4865,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4848,7 +4865,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
48484865
4849 const is_reg = constraint[0] == '{';4866 const is_reg = constraint[0] == '{';
4850 const input_val = try f.resolveInst(input);4867 const input_val = try f.resolveInst(input);
4851 if (asmInputNeedsLocal(constraint, input_val)) {4868 if (asmInputNeedsLocal(f, constraint, input_val)) {
4852 const input_ty = f.typeOf(input);4869 const input_ty = f.typeOf(input);
4853 if (is_reg) try writer.writeAll("register ");4870 if (is_reg) try writer.writeAll("register ");
4854 const alignment = 0;4871 const alignment = 0;
...@@ -4969,7 +4986,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4969,7 +4986,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue {
4969 const is_reg = constraint[0] == '{';4986 const is_reg = constraint[0] == '{';
4970 const input_val = try f.resolveInst(input);4987 const input_val = try f.resolveInst(input);
4971 try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)});4988 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: {
4973 const input_local = .{ .local = locals_index };4990 const input_local = .{ .local = locals_index };
4974 locals_index += 1;4991 locals_index += 1;
4975 break :local input_local;4992 break :local input_local;
src/codegen/llvm.zig+9-7
...@@ -417,7 +417,7 @@ const DataLayoutBuilder = struct {...@@ -417,7 +417,7 @@ const DataLayoutBuilder = struct {
417 if (idx != size) try writer.print(":{d}", .{idx});417 if (idx != size) try writer.print(":{d}", .{idx});
418 }418 }
419 }419 }
420 if (self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb())420 if (self.target.cpu.arch.isArmOrThumb())
421 try writer.writeAll("-Fi8"); // for thumb interwork421 try writer.writeAll("-Fi8"); // for thumb interwork
422 if (self.target.cpu.arch != .hexagon) {422 if (self.target.cpu.arch != .hexagon) {
423 if (self.target.cpu.arch == .s390x) try self.typeAlignment(.integer, 1, 8, 8, false, writer);423 if (self.target.cpu.arch == .s390x) try self.typeAlignment(.integer, 1, 8, 8, false, writer);
...@@ -620,7 +620,7 @@ const DataLayoutBuilder = struct {...@@ -620,7 +620,7 @@ const DataLayoutBuilder = struct {
620 else => {},620 else => {},
621 }621 }
622 },622 },
623 .vector => if (self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb()) {623 .vector => if (self.target.cpu.arch.isArmOrThumb()) {
624 switch (size) {624 switch (size) {
625 128 => abi = 64,625 128 => abi = 64,
626 else => {},626 else => {},
...@@ -670,7 +670,7 @@ const DataLayoutBuilder = struct {...@@ -670,7 +670,7 @@ const DataLayoutBuilder = struct {
670 else => {},670 else => {},
671 },671 },
672 .aggregate => if (self.target.os.tag == .uefi or self.target.os.tag == .windows or672 .aggregate => if (self.target.os.tag == .uefi or self.target.os.tag == .windows or
673 self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb())673 self.target.cpu.arch.isArmOrThumb())
674 {674 {
675 pref = @min(pref, self.target.ptrBitWidth());675 pref = @min(pref, self.target.ptrBitWidth());
676 } else if (self.target.cpu.arch == .hexagon) {676 } else if (self.target.cpu.arch == .hexagon) {
...@@ -6809,8 +6809,6 @@ pub const FuncGen = struct {...@@ -6809,8 +6809,6 @@ pub const FuncGen = struct {
6809 }6809 }
6810 llvm_constraints.appendAssumeCapacity('=');6810 llvm_constraints.appendAssumeCapacity('=');
68116811
6812 // Pass any non-return outputs indirectly, if the constraint accepts a memory location
6813 is_indirect.* = (output != .none) and constraintAllowsMemory(constraint);
6814 if (output != .none) {6812 if (output != .none) {
6815 const output_inst = try self.resolveInst(output);6813 const output_inst = try self.resolveInst(output);
6816 const output_ty = self.typeOf(output);6814 const output_ty = self.typeOf(output);
...@@ -6825,6 +6823,8 @@ pub const FuncGen = struct {...@@ -6825,6 +6823,8 @@ pub const FuncGen = struct {
6825 }),6823 }),
6826 }6824 }
68276825
6826 // Pass any non-return outputs indirectly, if the constraint accepts a memory location
6827 is_indirect.* = constraintAllowsMemory(constraint);
6828 if (is_indirect.*) {6828 if (is_indirect.*) {
6829 // Pass the result by reference as an indirect output (e.g. "=*m")6829 // Pass the result by reference as an indirect output (e.g. "=*m")
6830 llvm_constraints.appendAssumeCapacity('*');6830 llvm_constraints.appendAssumeCapacity('*');
...@@ -6841,11 +6841,13 @@ pub const FuncGen = struct {...@@ -6841,11 +6841,13 @@ pub const FuncGen = struct {
6841 } else {6841 } else {
6842 switch (constraint[0]) {6842 switch (constraint[0]) {
6843 '=' => {},6843 '=' => {},
6844 else => return self.todo("unsupported output constraint on result type '{c}'", .{6844 else => return self.todo("unsupported output constraint on result type '{s}'", .{
6845 constraint[0],6845 constraint,
6846 }),6846 }),
6847 }6847 }
68486848
6849 is_indirect.* = false;
6850
6849 const ret_ty = self.typeOfIndex(inst);6851 const ret_ty = self.typeOfIndex(inst);
6850 llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty);6852 llvm_ret_types[llvm_ret_i] = try o.lowerType(ret_ty);
6851 llvm_ret_i += 1;6853 llvm_ret_i += 1;
src/link/Elf.zig+1-1
...@@ -1654,7 +1654,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v...@@ -1654,7 +1654,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v
1654 }1654 }
16551655
1656 if (self.base.options.link_mode == .Static) {1656 if (self.base.options.link_mode == .Static) {
1657 if (target.cpu.arch.isARM() or target.cpu.arch.isThumb()) {1657 if (target.cpu.arch.isArmOrThumb()) {
1658 try argv.append("-Bstatic");1658 try argv.append("-Bstatic");
1659 } else {1659 } else {
1660 try argv.append("-static");1660 try argv.append("-static");
test/behavior/align.zig+3-2
...@@ -198,11 +198,12 @@ test "alignment and size of structs with 128-bit fields" {...@@ -198,11 +198,12 @@ test "alignment and size of structs with 128-bit fields" {
198198
199 else => return error.SkipZigTest,199 else => return error.SkipZigTest,
200 };200 };
201 const min_struct_align = if (builtin.zig_backend == .stage2_c) 16 else 0;
201 comptime {202 comptime {
202 assert(@alignOf(A) == expected.a_align);203 assert(@alignOf(A) == @max(expected.a_align, min_struct_align));
203 assert(@sizeOf(A) == expected.a_size);204 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));
206 assert(@sizeOf(B) == expected.b_size);207 assert(@sizeOf(B) == expected.b_size);
207208
208 assert(@alignOf(u128) == expected.u128_align);209 assert(@alignOf(u128) == expected.u128_align);
test/behavior/bitcast.zig+1-1
...@@ -421,7 +421,7 @@ test "bitcast nan float does modify signaling bit" {...@@ -421,7 +421,7 @@ test "bitcast nan float does modify signaling bit" {
421 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO421 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
422 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;422 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
423 // TODO: https://github.com/ziglang/zig/issues/14366423 // TODO: https://github.com/ziglang/zig/issues/14366
424 if (builtin.cpu.arch == .arm and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest;424 if (builtin.zig_backend == .stage2_llvm and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
425425
426 // 16 bit426 // 16 bit
427 const snan_f16_const = math.nan_f16;427 const snan_f16_const = math.nan_f16;
test/behavior/call_tail.zig+10-1
...@@ -32,7 +32,16 @@ noinline fn insertionSort(data: []u64) void {...@@ -32,7 +32,16 @@ noinline fn insertionSort(data: []u64) void {
3232
33test "arguments pointed to on stack into tailcall" {33test "arguments pointed to on stack into tailcall" {
34 switch (builtin.cpu.arch) {34 switch (builtin.cpu.arch) {
35 .wasm32, .mips, .mipsel, .powerpc, .powerpcle, .powerpc64le => return error.SkipZigTest,35 .wasm32,
36 .mips,
37 .mipsel,
38 .mips64,
39 .mips64el,
40 .powerpc,
41 .powerpcle,
42 .powerpc64,
43 .powerpc64le,
44 => return error.SkipZigTest,
36 else => {},45 else => {},
37 }46 }
38 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;47 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
test/behavior/cast.zig+2
...@@ -123,6 +123,7 @@ test "@floatFromInt(f80)" {...@@ -123,6 +123,7 @@ test "@floatFromInt(f80)" {
123 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO123 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
124 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO124 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
125 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;125 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
126 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
126127
127 const S = struct {128 const S = struct {
128 fn doTheTest(comptime Int: type) !void {129 fn doTheTest(comptime Int: type) !void {
...@@ -1369,6 +1370,7 @@ test "cast f16 to wider types" {...@@ -1369,6 +1370,7 @@ test "cast f16 to wider types" {
1369 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO1370 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1370 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1371 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1371 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1372 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1373 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
13721374
1373 const S = struct {1375 const S = struct {
1374 fn doTheTest() !void {1376 fn doTheTest() !void {
test/behavior/eval.zig+1
...@@ -533,6 +533,7 @@ test "runtime 128 bit integer division" {...@@ -533,6 +533,7 @@ test "runtime 128 bit integer division" {
533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO533 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
534 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO534 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
535 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;535 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
536 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
536537
537 var a: u128 = 152313999999999991610955792383;538 var a: u128 = 152313999999999991610955792383;
538 var b: u128 = 10000000000000000000;539 var b: u128 = 10000000000000000000;
test/behavior/floatop.zig+9
...@@ -554,6 +554,7 @@ test "another, possibly redundant, @fabs test" {...@@ -554,6 +554,7 @@ test "another, possibly redundant, @fabs test" {
554 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO554 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
555 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO555 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
556 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;556 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
557 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
557558
558 try testFabsLegacy(f128, 12.0);559 try testFabsLegacy(f128, 12.0);
559 try comptime testFabsLegacy(f128, 12.0);560 try comptime testFabsLegacy(f128, 12.0);
...@@ -576,6 +577,7 @@ test "@fabs f80" {...@@ -576,6 +577,7 @@ test "@fabs f80" {
576 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO577 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
577 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO578 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
578 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;579 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
580 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
579581
580 try testFabsLegacy(f80, 12.0);582 try testFabsLegacy(f80, 12.0);
581 try comptime testFabsLegacy(f80, 12.0);583 try comptime testFabsLegacy(f80, 12.0);
...@@ -593,6 +595,7 @@ test "a third @fabs test, surely there should not be three fabs tests" {...@@ -593,6 +595,7 @@ test "a third @fabs test, surely there should not be three fabs tests" {
593 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO595 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
594 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO596 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
595 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;597 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
598 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
596599
597 inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {600 inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| {
598 // normals601 // normals
...@@ -684,6 +687,7 @@ test "@floor f80" {...@@ -684,6 +687,7 @@ test "@floor f80" {
684 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO687 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
685 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO688 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
686 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;689 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
690 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
687691
688 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {692 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
689 // https://github.com/ziglang/zig/issues/12602693 // https://github.com/ziglang/zig/issues/12602
...@@ -700,6 +704,7 @@ test "@floor f128" {...@@ -700,6 +704,7 @@ test "@floor f128" {
700 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO704 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
701 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO705 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
702 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;706 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
707 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
703708
704 try testFloorLegacy(f128, 12.0);709 try testFloorLegacy(f128, 12.0);
705 try comptime testFloorLegacy(f128, 12.0);710 try comptime testFloorLegacy(f128, 12.0);
...@@ -780,6 +785,7 @@ test "@ceil f80" {...@@ -780,6 +785,7 @@ test "@ceil f80" {
780 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO785 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
781 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO786 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
782 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;787 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
788 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
783789
784 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {790 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
785 // https://github.com/ziglang/zig/issues/12602791 // https://github.com/ziglang/zig/issues/12602
...@@ -796,6 +802,7 @@ test "@ceil f128" {...@@ -796,6 +802,7 @@ test "@ceil f128" {
796 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO802 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
797 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO803 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
798 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;804 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
805 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
799806
800 try testCeilLegacy(f128, 12.0);807 try testCeilLegacy(f128, 12.0);
801 try comptime testCeilLegacy(f128, 12.0);808 try comptime testCeilLegacy(f128, 12.0);
...@@ -875,6 +882,7 @@ test "@trunc f80" {...@@ -875,6 +882,7 @@ test "@trunc f80" {
875 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO882 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
876 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO883 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
877 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;884 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
885 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
878886
879 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {887 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
880 // https://github.com/ziglang/zig/issues/12602888 // https://github.com/ziglang/zig/issues/12602
...@@ -897,6 +905,7 @@ test "@trunc f128" {...@@ -897,6 +905,7 @@ test "@trunc f128" {
897 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO905 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
898 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO906 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
899 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;907 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
908 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
900909
901 try testTruncLegacy(f128, 12.0);910 try testTruncLegacy(f128, 12.0);
902 try comptime testTruncLegacy(f128, 12.0);911 try comptime testTruncLegacy(f128, 12.0);
test/behavior/fn.zig+1
...@@ -151,6 +151,7 @@ fn fnWithUnreachable() noreturn {...@@ -151,6 +151,7 @@ fn fnWithUnreachable() noreturn {
151151
152test "extern struct with stdcallcc fn pointer" {152test "extern struct with stdcallcc fn pointer" {
153 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;153 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
154 if (builtin.zig_backend == .stage2_c and builtin.cpu.arch == .x86) return error.SkipZigTest;
154 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;155 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
155156
156 const S = extern struct {157 const S = extern struct {
test/behavior/math.zig+4
...@@ -664,6 +664,7 @@ test "128-bit multiplication" {...@@ -664,6 +664,7 @@ test "128-bit multiplication" {
664 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO664 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
665 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO665 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
666 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;666 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
667 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
667668
668 {669 {
669 var a: i128 = 3;670 var a: i128 = 3;
...@@ -1311,6 +1312,7 @@ test "remainder division" {...@@ -1311,6 +1312,7 @@ test "remainder division" {
1311 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1312 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1312 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1313 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1313 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1314 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1315 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
13141316
1315 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {1317 if (builtin.zig_backend == .stage2_llvm and builtin.os.tag == .windows) {
1316 // https://github.com/ziglang/zig/issues/126021318 // https://github.com/ziglang/zig/issues/12602
...@@ -1455,6 +1457,7 @@ test "@round f80" {...@@ -1455,6 +1457,7 @@ test "@round f80" {
1455 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1457 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1456 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1458 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1457 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1459 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1460 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
14581461
1459 try testRound(f80, 12.0);1462 try testRound(f80, 12.0);
1460 try comptime testRound(f80, 12.0);1463 try comptime testRound(f80, 12.0);
...@@ -1467,6 +1470,7 @@ test "@round f128" {...@@ -1467,6 +1470,7 @@ test "@round f128" {
1467 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO1470 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
1468 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO1471 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
1469 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;1472 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
1473 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
14701474
1471 try testRound(f128, 12.0);1475 try testRound(f128, 12.0);
1472 try comptime testRound(f128, 12.0);1476 try comptime testRound(f128, 12.0);
test/behavior/maximum_minimum.zig+1
...@@ -110,6 +110,7 @@ test "@min/max for floats" {...@@ -110,6 +110,7 @@ test "@min/max for floats" {
110 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO110 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
111 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO111 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
112 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;112 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
113 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
113114
114 const S = struct {115 const S = struct {
115 fn doTheTest(comptime T: type) !void {116 fn doTheTest(comptime T: type) !void {
test/behavior/muladd.zig+4
...@@ -56,6 +56,7 @@ test "@mulAdd f80" {...@@ -56,6 +56,7 @@ test "@mulAdd f80" {
56 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO56 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
57 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO57 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
58 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;58 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
59 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
5960
60 try comptime testMulAdd80();61 try comptime testMulAdd80();
61 try testMulAdd80();62 try testMulAdd80();
...@@ -75,6 +76,7 @@ test "@mulAdd f128" {...@@ -75,6 +76,7 @@ test "@mulAdd f128" {
75 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO76 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
76 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO77 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
77 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;78 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
79 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
7880
79 try comptime testMulAdd128();81 try comptime testMulAdd128();
80 try testMulAdd128();82 try testMulAdd128();
...@@ -177,6 +179,7 @@ test "vector f80" {...@@ -177,6 +179,7 @@ test "vector f80" {
177 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO179 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
178 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO180 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
179 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;181 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
182 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
180183
181 try comptime vector80();184 try comptime vector80();
182 try vector80();185 try vector80();
...@@ -201,6 +204,7 @@ test "vector f128" {...@@ -201,6 +204,7 @@ test "vector f128" {
201 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO204 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
202 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO205 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
203 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;206 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
207 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
204208
205 try comptime vector128();209 try comptime vector128();
206 try vector128();210 try vector128();
test/behavior/saturating_arithmetic.zig+1
...@@ -157,6 +157,7 @@ test "saturating multiplication" {...@@ -157,6 +157,7 @@ test "saturating multiplication" {
157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO157 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO158 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
159 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;159 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
160 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
160161
161 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .wasm32) {162 if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .wasm32) {
162 // https://github.com/ziglang/zig/issues/9660163 // https://github.com/ziglang/zig/issues/9660
test/behavior/struct.zig+3-2
...@@ -428,7 +428,7 @@ test "packed struct 24bits" {...@@ -428,7 +428,7 @@ test "packed struct 24bits" {
428 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO428 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
429 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO429 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
430 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO430 if (builtin.cpu.arch == .wasm32) return error.SkipZigTest; // TODO
431 if (builtin.cpu.arch == .arm) return error.SkipZigTest; // TODO431 if (comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; // TODO
432 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO432 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
433 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;433 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
434434
...@@ -824,6 +824,7 @@ test "non-packed struct with u128 entry in union" {...@@ -824,6 +824,7 @@ test "non-packed struct with u128 entry in union" {
824 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO824 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
825 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO825 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
826 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;826 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
827 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
827828
828 const U = union(enum) {829 const U = union(enum) {
829 Num: u128,830 Num: u128,
...@@ -944,7 +945,7 @@ test "comptime struct field" {...@@ -944,7 +945,7 @@ test "comptime struct field" {
944 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;945 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
945946
946 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO947 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
947 if (builtin.cpu.arch == .arm) return error.SkipZigTest; // TODO948 if (comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; // TODO
948949
949 const T = struct {950 const T = struct {
950 a: i32,951 a: i32,
test/behavior/var_args.zig+4-4
...@@ -101,7 +101,7 @@ test "simple variadic function" {...@@ -101,7 +101,7 @@ test "simple variadic function" {
101 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO101 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
102 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
103 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;103 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
104 if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos) {104 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {
105 // https://github.com/ziglang/zig/issues/14096105 // https://github.com/ziglang/zig/issues/14096
106 return error.SkipZigTest;106 return error.SkipZigTest;
107 }107 }
...@@ -151,7 +151,7 @@ test "variadic functions" {...@@ -151,7 +151,7 @@ test "variadic functions" {
151 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO151 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
152 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO152 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
153 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;153 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
154 if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos) {154 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {
155 // https://github.com/ziglang/zig/issues/14096155 // https://github.com/ziglang/zig/issues/14096
156 return error.SkipZigTest;156 return error.SkipZigTest;
157 }157 }
...@@ -195,7 +195,7 @@ test "copy VaList" {...@@ -195,7 +195,7 @@ test "copy VaList" {
195 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO195 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
196 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO196 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
197 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;197 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
198 if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos) {198 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {
199 // https://github.com/ziglang/zig/issues/14096199 // https://github.com/ziglang/zig/issues/14096
200 return error.SkipZigTest;200 return error.SkipZigTest;
201 }201 }
...@@ -228,7 +228,7 @@ test "unused VaList arg" {...@@ -228,7 +228,7 @@ test "unused VaList arg" {
228 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO228 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
229 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO229 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
230 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;230 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
231 if (builtin.cpu.arch == .aarch64 and builtin.os.tag != .macos) {231 if (builtin.os.tag != .macos and comptime builtin.cpu.arch.isAARCH64()) {
232 // https://github.com/ziglang/zig/issues/14096232 // https://github.com/ziglang/zig/issues/14096
233 return error.SkipZigTest;233 return error.SkipZigTest;
234 }234 }
test/behavior/vector.zig+3
...@@ -102,6 +102,7 @@ test "vector float operators" {...@@ -102,6 +102,7 @@ test "vector float operators" {
102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO102 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO103 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
104 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;104 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
105 if (builtin.zig_backend == .stage2_c and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
105106
106 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {107 inline for ([_]type{ f16, f32, f64, f80, f128 }) |T| {
107 const S = struct {108 const S = struct {
...@@ -494,6 +495,7 @@ test "vector division operators" {...@@ -494,6 +495,7 @@ test "vector division operators" {
494 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO495 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
495 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO496 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
496 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO497 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
498 if (builtin.zig_backend == .stage2_llvm and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest;
497 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO499 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
498 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;500 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
499501
...@@ -705,6 +707,7 @@ test "vector reduce operation" {...@@ -705,6 +707,7 @@ test "vector reduce operation" {
705 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO707 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
706 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO708 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
707 if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;709 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
709 const S = struct {712 const S = struct {
710 fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {713 fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void {
test/src/Cases.zig+1-1
...@@ -1524,7 +1524,7 @@ fn runOneCase(...@@ -1524,7 +1524,7 @@ fn runOneCase(
1524 }1524 }
1525 } else switch (host.getExternalExecutor(target_info, .{ .link_libc = case.link_libc })) {1525 } else switch (host.getExternalExecutor(target_info, .{ .link_libc = case.link_libc })) {
1526 .native => {1526 .native => {
1527 if (case.backend == .stage2 and case.target.getCpuArch() == .arm) {1527 if (case.backend == .stage2 and case.target.getCpuArch().isArmOrThumb()) {
1528 // https://github.com/ziglang/zig/issues/136231528 // https://github.com/ziglang/zig/issues/13623
1529 continue :update; // Pass test.1529 continue :update; // Pass test.
1530 }1530 }
test/tests.zig+1
...@@ -1053,6 +1053,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {...@@ -1053,6 +1053,7 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step {
1053 // TODO stop violating these pedantic errors. spotted on linux1053 // TODO stop violating these pedantic errors. spotted on linux
1054 "-Wno-address-of-packed-member",1054 "-Wno-address-of-packed-member",
1055 "-Wno-gnu-folding-constant",1055 "-Wno-gnu-folding-constant",
1056 "-Wno-incompatible-function-pointer-types",
1056 "-Wno-incompatible-pointer-types",1057 "-Wno-incompatible-pointer-types",
1057 "-Wno-overlength-strings",1058 "-Wno-overlength-strings",
1058 // TODO stop violating these pedantic errors. spotted on darwin1059 // TODO stop violating these pedantic errors. spotted on darwin