| author | |
| committer | |
| log | 817fa3af8631d894004fbdb668da0882836dbe9b |
| tree | 3e63751b5ebb46fe8c45eca41a5248075d97bda8 |
| parent | 43b830415368ac4fb08bf5e154a222a38baf4a24 |
After fixing some issues with inline assembly in the C backend, the std
cleanups have the side effect of making these functions compatible with
the backend, allowing it to be used on linux without linking libc.10 files changed, 278 insertions(+), 222 deletions(-)
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, // Data | 1279 | .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 | } |
| 1286 | 1288 |
lib/std/os/linux/arm-eabi.zig+26-2| ... | @@ -104,7 +104,19 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8; | ... | @@ -104,7 +104,19 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8; |
| 104 | pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | 104 | pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; |
| 105 | 105 | ||
| 106 | pub fn restore() callconv(.Naked) void { | 106 | pub fn restore() callconv(.Naked) void { |
| 107 | return asm volatile ("svc #0" | 107 | if (@import("builtin").zig_backend == .stage2_c) { |
| 108 | asm volatile ( | ||
| 109 | \\ mov r7, %[number] | ||
| 110 | \\ svc #0 | ||
| 111 | \\ bx lr | ||
| 112 | : | ||
| 113 | : [number] "i" (@intFromEnum(SYS.sigreturn)), | ||
| 114 | : "memory" | ||
| 115 | ); | ||
| 116 | unreachable; | ||
| 117 | } | ||
| 118 | |||
| 119 | asm volatile ("svc #0" | ||
| 108 | : | 120 | : |
| 109 | : [number] "{r7}" (@intFromEnum(SYS.sigreturn)), | 121 | : [number] "{r7}" (@intFromEnum(SYS.sigreturn)), |
| 110 | : "memory" | 122 | : "memory" |
| ... | @@ -112,7 +124,19 @@ pub fn restore() callconv(.Naked) void { | ... | @@ -112,7 +124,19 @@ pub fn restore() callconv(.Naked) void { |
| 112 | } | 124 | } |
| 113 | 125 | ||
| 114 | pub fn restore_rt() callconv(.Naked) void { | 126 | pub fn restore_rt() callconv(.Naked) void { |
| 115 | return asm volatile ("svc #0" | 127 | if (@import("builtin").zig_backend == .stage2_c) { |
| 128 | asm volatile ( | ||
| 129 | \\ mov r7, %[number] | ||
| 130 | \\ svc #0 | ||
| 131 | \\ bx lr | ||
| 132 | : | ||
| 133 | : [number] "i" (@intFromEnum(SYS.rt_sigreturn)), | ||
| 134 | : "memory" | ||
| 135 | ); | ||
| 136 | unreachable; | ||
| 137 | } | ||
| 138 | |||
| 139 | asm volatile ("svc #0" | ||
| 116 | : | 140 | : |
| 117 | : [number] "{r7}" (@intFromEnum(SYS.rt_sigreturn)), | 141 | : [number] "{r7}" (@intFromEnum(SYS.rt_sigreturn)), |
| 118 | : "memory" | 142 | : "memory" |
lib/std/os/linux/arm64.zig+12-8| ... | @@ -106,20 +106,24 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: * | ... | @@ -106,20 +106,24 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: * |
| 106 | pub const restore = restore_rt; | 106 | pub const restore = restore_rt; |
| 107 | 107 | ||
| 108 | pub fn restore_rt() callconv(.Naked) void { | 108 | pub fn restore_rt() callconv(.Naked) void { |
| 109 | switch (@import("builtin").zig_backend) { | 109 | if (@import("builtin").zig_backend == .stage2_c) { |
| 110 | .stage2_c => return asm volatile ( | 110 | asm volatile ( |
| 111 | \\ mov x8, %[number] | 111 | \\ mov x8, %[number] |
| 112 | \\ svc #0 | 112 | \\ svc #0 |
| 113 | \\ ret | ||
| 113 | : | 114 | : |
| 114 | : [number] "i" (@intFromEnum(SYS.rt_sigreturn)), | 115 | : [number] "i" (@intFromEnum(SYS.rt_sigreturn)), |
| 115 | : "memory", "cc" | 116 | : "memory", "cc" |
| 116 | ), | 117 | ); |
| 117 | else => return asm volatile ("svc #0" | 118 | unreachable; |
| 118 | : | ||
| 119 | : [number] "{x8}" (@intFromEnum(SYS.rt_sigreturn)), | ||
| 120 | : "memory", "cc" | ||
| 121 | ), | ||
| 122 | } | 119 | } |
| 120 | |||
| 121 | asm volatile ( | ||
| 122 | \\ svc #0 | ||
| 123 | : | ||
| 124 | : [number] "{x8}" (@intFromEnum(SYS.rt_sigreturn)), | ||
| 125 | : "memory", "cc" | ||
| 126 | ); | ||
| 123 | } | 127 | } |
| 124 | 128 | ||
| 125 | pub const O = struct { | 129 | pub const O = struct { |
lib/std/os/linux/tls.zig+8-6| ... | @@ -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, // Data | 119 | .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); |
lib/std/os/linux/x86.zig+76-71| ... | @@ -124,45 +124,45 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8; | ... | @@ -124,45 +124,45 @@ const CloneFn = *const fn (arg: usize) callconv(.C) u8; |
| 124 | pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; | 124 | pub extern fn clone(func: CloneFn, stack: usize, flags: u32, arg: usize, ptid: *i32, tls: usize, ctid: *i32) usize; |
| 125 | 125 | ||
| 126 | pub fn restore() callconv(.Naked) void { | 126 | pub fn restore() callconv(.Naked) void { |
| 127 | switch (@import("builtin").zig_backend) { | 127 | if (@import("builtin").zig_backend == .stage2_c) { |
| 128 | .stage2_c => asm volatile ( | 128 | asm volatile ( |
| 129 | \\ movl %[number], %%eax | 129 | \\ movl %[number], %%eax |
| 130 | \\ int $0x80 | 130 | \\ int $0x80 |
| 131 | \\ ret | 131 | \\ retl |
| 132 | : | 132 | : |
| 133 | : [number] "i" (@intFromEnum(SYS.sigreturn)), | 133 | : [number] "i" (@intFromEnum(SYS.sigreturn)), |
| 134 | : "memory" | 134 | : "memory" |
| 135 | ), | 135 | ); |
| 136 | else => asm volatile ( | 136 | unreachable; |
| 137 | \\ int $0x80 | ||
| 138 | \\ ret | ||
| 139 | : | ||
| 140 | : [number] "{eax}" (@intFromEnum(SYS.sigreturn)), | ||
| 141 | : "memory" | ||
| 142 | ), | ||
| 143 | } | 137 | } |
| 144 | unreachable; | 138 | |
| 139 | asm volatile ( | ||
| 140 | \\ int $0x80 | ||
| 141 | : | ||
| 142 | : [number] "{eax}" (@intFromEnum(SYS.sigreturn)), | ||
| 143 | : "memory" | ||
| 144 | ); | ||
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | pub fn restore_rt() callconv(.Naked) void { | 147 | pub fn restore_rt() callconv(.Naked) void { |
| 148 | switch (@import("builtin").zig_backend) { | 148 | if (@import("builtin").zig_backend == .stage2_c) { |
| 149 | .stage2_c => asm volatile ( | 149 | asm volatile ( |
| 150 | \\ movl %[number], %%eax | 150 | \\ movl %[number], %%eax |
| 151 | \\ int $0x80 | 151 | \\ int $0x80 |
| 152 | \\ ret | 152 | \\ retl |
| 153 | : | 153 | : |
| 154 | : [number] "i" (@intFromEnum(SYS.rt_sigreturn)), | 154 | : [number] "i" (@intFromEnum(SYS.rt_sigreturn)), |
| 155 | : "memory" | 155 | : "memory" |
| 156 | ), | 156 | ); |
| 157 | else => asm volatile ( | 157 | unreachable; |
| 158 | \\ int $0x80 | ||
| 159 | \\ ret | ||
| 160 | : | ||
| 161 | : [number] "{eax}" (@intFromEnum(SYS.rt_sigreturn)), | ||
| 162 | : "memory" | ||
| 163 | ), | ||
| 164 | } | 158 | } |
| 165 | unreachable; | 159 | |
| 160 | asm volatile ( | ||
| 161 | \\ int $0x80 | ||
| 162 | : | ||
| 163 | : [number] "{eax}" (@intFromEnum(SYS.rt_sigreturn)), | ||
| 164 | : "memory" | ||
| 165 | ); | ||
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | pub const O = struct { | 168 | pub const O = struct { |
| ... | @@ -354,16 +354,19 @@ pub const ucontext_t = extern struct { | ... | @@ -354,16 +354,19 @@ pub const ucontext_t = extern struct { |
| 354 | 354 | ||
| 355 | pub const Elf_Symndx = u32; | 355 | pub const Elf_Symndx = u32; |
| 356 | 356 | ||
| 357 | pub const user_desc = packed struct { | 357 | pub const user_desc = extern struct { |
| 358 | entry_number: u32, | 358 | entry_number: u32, |
| 359 | base_addr: u32, | 359 | base_addr: u32, |
| 360 | limit: u32, | 360 | limit: u32, |
| 361 | seg_32bit: u1, | 361 | flags: packed struct(u32) { |
| 362 | contents: u2, | 362 | seg_32bit: u1, |
| 363 | read_exec_only: u1, | 363 | contents: u2, |
| 364 | limit_in_pages: u1, | 364 | read_exec_only: u1, |
| 365 | seg_not_present: u1, | 365 | limit_in_pages: u1, |
| 366 | useable: u1, | 366 | seg_not_present: u1, |
| 367 | useable: u1, | ||
| 368 | _: u25 = undefined, | ||
| 369 | }, | ||
| 367 | }; | 370 | }; |
| 368 | 371 | ||
| 369 | /// socketcall() call numbers | 372 | /// socketcall() call numbers |
| ... | @@ -400,63 +403,63 @@ noinline fn getContextReturnAddress() usize { | ... | @@ -400,63 +403,63 @@ noinline fn getContextReturnAddress() usize { |
| 400 | 403 | ||
| 401 | pub fn getContextInternal() callconv(.Naked) void { | 404 | pub fn getContextInternal() callconv(.Naked) void { |
| 402 | asm volatile ( | 405 | asm volatile ( |
| 403 | \\ movl $0, (%[flags_offset])(%%edx) | 406 | \\ movl $0, %[flags_offset:c](%%edx) |
| 404 | \\ movl $0, (%[link_offset])(%%edx) | 407 | \\ movl $0, %[link_offset:c](%%edx) |
| 405 | \\ movl %%edi, (%[edi_offset])(%%edx) | 408 | \\ movl %%edi, %[edi_offset:c](%%edx) |
| 406 | \\ movl %%esi, (%[esi_offset])(%%edx) | 409 | \\ movl %%esi, %[esi_offset:c](%%edx) |
| 407 | \\ movl %%ebp, (%[ebp_offset])(%%edx) | 410 | \\ movl %%ebp, %[ebp_offset:c](%%edx) |
| 408 | \\ movl %%ebx, (%[ebx_offset])(%%edx) | 411 | \\ movl %%ebx, %[ebx_offset:c](%%edx) |
| 409 | \\ movl %%edx, (%[edx_offset])(%%edx) | 412 | \\ movl %%edx, %[edx_offset:c](%%edx) |
| 410 | \\ movl %%ecx, (%[ecx_offset])(%%edx) | 413 | \\ movl %%ecx, %[ecx_offset:c](%%edx) |
| 411 | \\ movl %%eax, (%[eax_offset])(%%edx) | 414 | \\ movl %%eax, %[eax_offset:c](%%edx) |
| 412 | \\ movl (%%esp), %%ecx | 415 | \\ movl (%%esp), %%ecx |
| 413 | \\ movl %%ecx, (%[eip_offset])(%%edx) | 416 | \\ movl %%ecx, %[eip_offset:c](%%edx) |
| 414 | \\ leal 4(%%esp), %%ecx | 417 | \\ leal 4(%%esp), %%ecx |
| 415 | \\ movl %%ecx, (%[esp_offset])(%%edx) | 418 | \\ movl %%ecx, %[esp_offset:c](%%edx) |
| 416 | \\ xorl %%ecx, %%ecx | 419 | \\ xorl %%ecx, %%ecx |
| 417 | \\ movw %%fs, %%cx | 420 | \\ movw %%fs, %%cx |
| 418 | \\ movl %%ecx, (%[fs_offset])(%%edx) | 421 | \\ movl %%ecx, %[fs_offset:c](%%edx) |
| 419 | \\ leal (%[regspace_offset])(%%edx), %%ecx | 422 | \\ leal %[regspace_offset:c](%%edx), %%ecx |
| 420 | \\ movl %%ecx, (%[fpregs_offset])(%%edx) | 423 | \\ movl %%ecx, %[fpregs_offset:c](%%edx) |
| 421 | \\ fnstenv (%%ecx) | 424 | \\ fnstenv (%%ecx) |
| 422 | \\ fldenv (%%ecx) | 425 | \\ fldenv (%%ecx) |
| 423 | \\ pushl %%ebx | 426 | \\ pushl %%ebx |
| 424 | \\ pushl %%esi | 427 | \\ pushl %%esi |
| 425 | \\ xorl %%ebx, %%ebx | 428 | \\ xorl %%ebx, %%ebx |
| 426 | \\ movl %[sigaltstack], %%eax | 429 | \\ movl %[sigaltstack], %%eax |
| 427 | \\ leal (%[stack_offset])(%%edx), %%ecx | 430 | \\ leal %[stack_offset:c](%%edx), %%ecx |
| 428 | \\ int $0x80 | 431 | \\ int $0x80 |
| 429 | \\ cmpl $0, %%eax | 432 | \\ testl %%eax, %%eax |
| 430 | \\ jne return | 433 | \\ jnz 0f |
| 431 | \\ movl %[sigprocmask], %%eax | 434 | \\ movl %[sigprocmask], %%eax |
| 432 | \\ xorl %%ecx, %%ecx | 435 | \\ xorl %%ecx, %%ecx |
| 433 | \\ leal (%[sigmask_offset])(%%edx), %%edx | 436 | \\ leal %[sigmask_offset:c](%%edx), %%edx |
| 434 | \\ movl %[sigset_size], %%esi | 437 | \\ movl %[sigset_size], %%esi |
| 435 | \\ int $0x80 | 438 | \\ int $0x80 |
| 436 | \\ return: | 439 | \\0: |
| 437 | \\ popl %%esi | 440 | \\ popl %%esi |
| 438 | \\ popl %%ebx | 441 | \\ popl %%ebx |
| 439 | : | 442 | : |
| 440 | : [flags_offset] "p" (@offsetOf(ucontext_t, "flags")), | 443 | : [flags_offset] "i" (@offsetOf(ucontext_t, "flags")), |
| 441 | [link_offset] "p" (@offsetOf(ucontext_t, "link")), | 444 | [link_offset] "i" (@offsetOf(ucontext_t, "link")), |
| 442 | [edi_offset] "p" (comptime gpRegisterOffset(REG.EDI)), | 445 | [edi_offset] "i" (comptime gpRegisterOffset(REG.EDI)), |
| 443 | [esi_offset] "p" (comptime gpRegisterOffset(REG.ESI)), | 446 | [esi_offset] "i" (comptime gpRegisterOffset(REG.ESI)), |
| 444 | [ebp_offset] "p" (comptime gpRegisterOffset(REG.EBP)), | 447 | [ebp_offset] "i" (comptime gpRegisterOffset(REG.EBP)), |
| 445 | [esp_offset] "p" (comptime gpRegisterOffset(REG.ESP)), | 448 | [esp_offset] "i" (comptime gpRegisterOffset(REG.ESP)), |
| 446 | [ebx_offset] "p" (comptime gpRegisterOffset(REG.EBX)), | 449 | [ebx_offset] "i" (comptime gpRegisterOffset(REG.EBX)), |
| 447 | [edx_offset] "p" (comptime gpRegisterOffset(REG.EDX)), | 450 | [edx_offset] "i" (comptime gpRegisterOffset(REG.EDX)), |
| 448 | [ecx_offset] "p" (comptime gpRegisterOffset(REG.ECX)), | 451 | [ecx_offset] "i" (comptime gpRegisterOffset(REG.ECX)), |
| 449 | [eax_offset] "p" (comptime gpRegisterOffset(REG.EAX)), | 452 | [eax_offset] "i" (comptime gpRegisterOffset(REG.EAX)), |
| 450 | [eip_offset] "p" (comptime gpRegisterOffset(REG.EIP)), | 453 | [eip_offset] "i" (comptime gpRegisterOffset(REG.EIP)), |
| 451 | [fs_offset] "p" (comptime gpRegisterOffset(REG.FS)), | 454 | [fs_offset] "i" (comptime gpRegisterOffset(REG.FS)), |
| 452 | [fpregs_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")), | 455 | [fpregs_offset] "i" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")), |
| 453 | [regspace_offset] "p" (@offsetOf(ucontext_t, "regspace")), | 456 | [regspace_offset] "i" (@offsetOf(ucontext_t, "regspace")), |
| 454 | [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)), | 457 | [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)), |
| 455 | [stack_offset] "p" (@offsetOf(ucontext_t, "stack")), | 458 | [stack_offset] "i" (@offsetOf(ucontext_t, "stack")), |
| 456 | [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)), | 459 | [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)), |
| 457 | [sigmask_offset] "p" (@offsetOf(ucontext_t, "sigmask")), | 460 | [sigmask_offset] "i" (@offsetOf(ucontext_t, "sigmask")), |
| 458 | [sigset_size] "i" (linux.NSIG / 8), | 461 | [sigset_size] "i" (linux.NSIG / 8), |
| 459 | : "memory", "eax", "ecx", "edx" | 462 | : "cc", "memory", "eax", "ecx", "edx" |
| 460 | ); | 463 | ); |
| 461 | } | 464 | } |
| 462 | 465 | ||
| ... | @@ -464,11 +467,13 @@ pub inline fn getcontext(context: *ucontext_t) usize { | ... | @@ -464,11 +467,13 @@ pub inline fn getcontext(context: *ucontext_t) usize { |
| 464 | // This method is used so that getContextInternal can control | 467 | // This method is used so that getContextInternal can control |
| 465 | // its prologue in order to read ESP from a constant offset. | 468 | // 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. | 469 | // The unused &getContextInternal input is required so the function is included in the binary. |
| 470 | var clobber_edx: usize = undefined; | ||
| 467 | return asm volatile ( | 471 | return asm volatile ( |
| 468 | \\ call os.linux.x86.getContextInternal | 472 | \\ calll %[getContextInternal:P] |
| 469 | : [ret] "={eax}" (-> usize), | 473 | : [_] "={eax}" (-> usize), |
| 470 | : [context] "{edx}" (context), | 474 | [_] "={edx}" (clobber_edx), |
| 475 | : [_] "{edx}" (context), | ||
| 471 | [getContextInternal] "X" (&getContextInternal), | 476 | [getContextInternal] "X" (&getContextInternal), |
| 472 | : "memory", "ecx" | 477 | : "cc", "memory", "ecx" |
| 473 | ); | 478 | ); |
| 474 | } | 479 | } |
lib/std/os/linux/x86_64.zig+74-72| ... | @@ -108,24 +108,24 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: | ... | @@ -108,24 +108,24 @@ pub extern fn clone(func: CloneFn, stack: usize, flags: usize, arg: usize, ptid: |
| 108 | pub const restore = restore_rt; | 108 | pub const restore = restore_rt; |
| 109 | 109 | ||
| 110 | pub fn restore_rt() callconv(.Naked) void { | 110 | pub fn restore_rt() callconv(.Naked) void { |
| 111 | switch (@import("builtin").zig_backend) { | 111 | if (@import("builtin").zig_backend == .stage2_c) { |
| 112 | .stage2_c => asm volatile ( | 112 | asm volatile ( |
| 113 | \\ movl %[number], %%eax | 113 | \\ movl %[number], %%eax |
| 114 | \\ syscall | 114 | \\ syscall |
| 115 | \\ retq | 115 | \\ retq |
| 116 | : | 116 | : |
| 117 | : [number] "i" (@intFromEnum(SYS.rt_sigreturn)), | 117 | : [number] "i" (@intFromEnum(SYS.rt_sigreturn)), |
| 118 | : "rcx", "r11", "memory" | 118 | : "rcx", "r11", "memory" |
| 119 | ), | 119 | ); |
| 120 | else => asm volatile ( | 120 | unreachable; |
| 121 | \\ syscall | ||
| 122 | \\ retq | ||
| 123 | : | ||
| 124 | : [number] "{rax}" (@intFromEnum(SYS.rt_sigreturn)), | ||
| 125 | : "rcx", "r11", "memory" | ||
| 126 | ), | ||
| 127 | } | 121 | } |
| 128 | unreachable; | 122 | |
| 123 | asm volatile ( | ||
| 124 | \\ syscall | ||
| 125 | : | ||
| 126 | : [number] "{rax}" (@intFromEnum(SYS.rt_sigreturn)), | ||
| 127 | : "rcx", "r11", "memory" | ||
| 128 | ); | ||
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | pub const mode_t = usize; | 131 | pub const mode_t = usize; |
| ... | @@ -403,77 +403,77 @@ fn gpRegisterOffset(comptime reg_index: comptime_int) usize { | ... | @@ -403,77 +403,77 @@ fn gpRegisterOffset(comptime reg_index: comptime_int) usize { |
| 403 | fn getContextInternal() callconv(.Naked) void { | 403 | fn getContextInternal() callconv(.Naked) void { |
| 404 | // TODO: Read GS/FS registers? | 404 | // TODO: Read GS/FS registers? |
| 405 | asm volatile ( | 405 | asm volatile ( |
| 406 | \\ movq $0, (%[flags_offset])(%%rdi) | 406 | \\ movq $0, %[flags_offset:c](%%rdi) |
| 407 | \\ movq $0, (%[link_offset])(%%rdi) | 407 | \\ movq $0, %[link_offset:c](%%rdi) |
| 408 | \\ movq %%r8, (%[r8_offset])(%%rdi) | 408 | \\ movq %%r8, %[r8_offset:c](%%rdi) |
| 409 | \\ movq %%r9, (%[r9_offset])(%%rdi) | 409 | \\ movq %%r9, %[r9_offset:c](%%rdi) |
| 410 | \\ movq %%r10, (%[r10_offset])(%%rdi) | 410 | \\ movq %%r10, %[r10_offset:c](%%rdi) |
| 411 | \\ movq %%r11, (%[r11_offset])(%%rdi) | 411 | \\ movq %%r11, %[r11_offset:c](%%rdi) |
| 412 | \\ movq %%r12, (%[r12_offset])(%%rdi) | 412 | \\ movq %%r12, %[r12_offset:c](%%rdi) |
| 413 | \\ movq %%r13, (%[r13_offset])(%%rdi) | 413 | \\ movq %%r13, %[r13_offset:c](%%rdi) |
| 414 | \\ movq %%r14, (%[r14_offset])(%%rdi) | 414 | \\ movq %%r14, %[r14_offset:c](%%rdi) |
| 415 | \\ movq %%r15, (%[r15_offset])(%%rdi) | 415 | \\ movq %%r15, %[r15_offset:c](%%rdi) |
| 416 | \\ movq %%rdi, (%[rdi_offset])(%%rdi) | 416 | \\ movq %%rdi, %[rdi_offset:c](%%rdi) |
| 417 | \\ movq %%rsi, (%[rsi_offset])(%%rdi) | 417 | \\ movq %%rsi, %[rsi_offset:c](%%rdi) |
| 418 | \\ movq %%rbp, (%[rbp_offset])(%%rdi) | 418 | \\ movq %%rbp, %[rbp_offset:c](%%rdi) |
| 419 | \\ movq %%rbx, (%[rbx_offset])(%%rdi) | 419 | \\ movq %%rbx, %[rbx_offset:c](%%rdi) |
| 420 | \\ movq %%rdx, (%[rdx_offset])(%%rdi) | 420 | \\ movq %%rdx, %[rdx_offset:c](%%rdi) |
| 421 | \\ movq %%rax, (%[rax_offset])(%%rdi) | 421 | \\ movq %%rax, %[rax_offset:c](%%rdi) |
| 422 | \\ movq %%rcx, (%[rcx_offset])(%%rdi) | 422 | \\ movq %%rcx, %[rcx_offset:c](%%rdi) |
| 423 | \\ movq (%%rsp), %%rcx | 423 | \\ movq (%%rsp), %%rcx |
| 424 | \\ movq %%rcx, (%[rip_offset])(%%rdi) | 424 | \\ movq %%rcx, %[rip_offset:c](%%rdi) |
| 425 | \\ leaq 8(%%rsp), %%rcx | 425 | \\ leaq 8(%%rsp), %%rcx |
| 426 | \\ movq %%rcx, (%[rsp_offset])(%%rdi) | 426 | \\ movq %%rcx, %[rsp_offset:c](%%rdi) |
| 427 | \\ pushfq | 427 | \\ pushfq |
| 428 | \\ popq (%[efl_offset])(%%rdi) | 428 | \\ popq %[efl_offset:c](%%rdi) |
| 429 | \\ leaq (%[fpmem_offset])(%%rdi), %%rcx | 429 | \\ leaq %[fpmem_offset:c](%%rdi), %%rcx |
| 430 | \\ movq %%rcx, (%[fpstate_offset])(%%rdi) | 430 | \\ movq %%rcx, %[fpstate_offset:c](%%rdi) |
| 431 | \\ fnstenv (%%rcx) | 431 | \\ fnstenv (%%rcx) |
| 432 | \\ fldenv (%%rcx) | 432 | \\ fldenv (%%rcx) |
| 433 | \\ stmxcsr (%[mxcsr_offset])(%%rdi) | 433 | \\ stmxcsr %[mxcsr_offset:c](%%rdi) |
| 434 | \\ leaq (%[stack_offset])(%%rdi), %%rsi | 434 | \\ leaq %[stack_offset:c](%%rdi), %%rsi |
| 435 | \\ movq %%rdi, %%r8 | 435 | \\ movq %%rdi, %%r8 |
| 436 | \\ xorq %%rdi, %%rdi | 436 | \\ xorl %%edi, %%edi |
| 437 | \\ movq %[sigaltstack], %%rax | 437 | \\ movq %[sigaltstack], %%rax |
| 438 | \\ syscall | 438 | \\ syscall |
| 439 | \\ cmpq $0, %%rax | 439 | \\ testq %%rax, %%rax |
| 440 | \\ jne return | 440 | \\ jnz 0f |
| 441 | \\ movq %[sigprocmask], %%rax | 441 | \\ movq %[sigprocmask], %%rax |
| 442 | \\ xorq %%rsi, %%rsi | 442 | \\ xorl %%esi, %%esi |
| 443 | \\ leaq (%[sigmask_offset])(%%r8), %%rdx | 443 | \\ leaq %[sigmask_offset:c](%%r8), %%rdx |
| 444 | \\ movq %[sigset_size], %%r10 | 444 | \\ movl %[sigset_size], %%r10d |
| 445 | \\ syscall | 445 | \\ syscall |
| 446 | \\ return: | 446 | \\0: |
| 447 | : | 447 | : |
| 448 | : [flags_offset] "p" (@offsetOf(ucontext_t, "flags")), | 448 | : [flags_offset] "i" (@offsetOf(ucontext_t, "flags")), |
| 449 | [link_offset] "p" (@offsetOf(ucontext_t, "link")), | 449 | [link_offset] "i" (@offsetOf(ucontext_t, "link")), |
| 450 | [r8_offset] "p" (comptime gpRegisterOffset(REG.R8)), | 450 | [r8_offset] "i" (comptime gpRegisterOffset(REG.R8)), |
| 451 | [r9_offset] "p" (comptime gpRegisterOffset(REG.R9)), | 451 | [r9_offset] "i" (comptime gpRegisterOffset(REG.R9)), |
| 452 | [r10_offset] "p" (comptime gpRegisterOffset(REG.R10)), | 452 | [r10_offset] "i" (comptime gpRegisterOffset(REG.R10)), |
| 453 | [r11_offset] "p" (comptime gpRegisterOffset(REG.R11)), | 453 | [r11_offset] "i" (comptime gpRegisterOffset(REG.R11)), |
| 454 | [r12_offset] "p" (comptime gpRegisterOffset(REG.R12)), | 454 | [r12_offset] "i" (comptime gpRegisterOffset(REG.R12)), |
| 455 | [r13_offset] "p" (comptime gpRegisterOffset(REG.R13)), | 455 | [r13_offset] "i" (comptime gpRegisterOffset(REG.R13)), |
| 456 | [r14_offset] "p" (comptime gpRegisterOffset(REG.R14)), | 456 | [r14_offset] "i" (comptime gpRegisterOffset(REG.R14)), |
| 457 | [r15_offset] "p" (comptime gpRegisterOffset(REG.R15)), | 457 | [r15_offset] "i" (comptime gpRegisterOffset(REG.R15)), |
| 458 | [rdi_offset] "p" (comptime gpRegisterOffset(REG.RDI)), | 458 | [rdi_offset] "i" (comptime gpRegisterOffset(REG.RDI)), |
| 459 | [rsi_offset] "p" (comptime gpRegisterOffset(REG.RSI)), | 459 | [rsi_offset] "i" (comptime gpRegisterOffset(REG.RSI)), |
| 460 | [rbp_offset] "p" (comptime gpRegisterOffset(REG.RBP)), | 460 | [rbp_offset] "i" (comptime gpRegisterOffset(REG.RBP)), |
| 461 | [rbx_offset] "p" (comptime gpRegisterOffset(REG.RBX)), | 461 | [rbx_offset] "i" (comptime gpRegisterOffset(REG.RBX)), |
| 462 | [rdx_offset] "p" (comptime gpRegisterOffset(REG.RDX)), | 462 | [rdx_offset] "i" (comptime gpRegisterOffset(REG.RDX)), |
| 463 | [rax_offset] "p" (comptime gpRegisterOffset(REG.RAX)), | 463 | [rax_offset] "i" (comptime gpRegisterOffset(REG.RAX)), |
| 464 | [rcx_offset] "p" (comptime gpRegisterOffset(REG.RCX)), | 464 | [rcx_offset] "i" (comptime gpRegisterOffset(REG.RCX)), |
| 465 | [rsp_offset] "p" (comptime gpRegisterOffset(REG.RSP)), | 465 | [rsp_offset] "i" (comptime gpRegisterOffset(REG.RSP)), |
| 466 | [rip_offset] "p" (comptime gpRegisterOffset(REG.RIP)), | 466 | [rip_offset] "i" (comptime gpRegisterOffset(REG.RIP)), |
| 467 | [efl_offset] "p" (comptime gpRegisterOffset(REG.EFL)), | 467 | [efl_offset] "i" (comptime gpRegisterOffset(REG.EFL)), |
| 468 | [fpstate_offset] "p" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")), | 468 | [fpstate_offset] "i" (@offsetOf(ucontext_t, "mcontext") + @offsetOf(mcontext_t, "fpregs")), |
| 469 | [fpmem_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem")), | 469 | [fpmem_offset] "i" (@offsetOf(ucontext_t, "fpregs_mem")), |
| 470 | [mxcsr_offset] "p" (@offsetOf(ucontext_t, "fpregs_mem") + @offsetOf(fpstate, "mxcsr")), | 470 | [mxcsr_offset] "i" (@offsetOf(ucontext_t, "fpregs_mem") + @offsetOf(fpstate, "mxcsr")), |
| 471 | [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)), | 471 | [sigaltstack] "i" (@intFromEnum(linux.SYS.sigaltstack)), |
| 472 | [stack_offset] "p" (@offsetOf(ucontext_t, "stack")), | 472 | [stack_offset] "i" (@offsetOf(ucontext_t, "stack")), |
| 473 | [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)), | 473 | [sigprocmask] "i" (@intFromEnum(linux.SYS.rt_sigprocmask)), |
| 474 | [sigmask_offset] "p" (@offsetOf(ucontext_t, "sigmask")), | 474 | [sigmask_offset] "i" (@offsetOf(ucontext_t, "sigmask")), |
| 475 | [sigset_size] "i" (linux.NSIG / 8), | 475 | [sigset_size] "i" (linux.NSIG / 8), |
| 476 | : "memory", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11" | 476 | : "cc", "memory", "rax", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11" |
| 477 | ); | 477 | ); |
| 478 | } | 478 | } |
| 479 | 479 | ||
| ... | @@ -481,11 +481,13 @@ pub inline fn getcontext(context: *ucontext_t) usize { | ... | @@ -481,11 +481,13 @@ pub inline fn getcontext(context: *ucontext_t) usize { |
| 481 | // This method is used so that getContextInternal can control | 481 | // This method is used so that getContextInternal can control |
| 482 | // its prologue in order to read RSP from a constant offset | 482 | // 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. | 483 | // The unused &getContextInternal input is required so the function is included in the binary. |
| 484 | var clobber_rdi: usize = undefined; | ||
| 484 | return asm volatile ( | 485 | return asm volatile ( |
| 485 | \\ call os.linux.x86_64.getContextInternal | 486 | \\ callq %[getContextInternal:P] |
| 486 | : [ret] "={rax}" (-> usize), | 487 | : [_] "={rax}" (-> usize), |
| 487 | : [context] "{rdi}" (context), | 488 | [_] "={rdi}" (clobber_rdi), |
| 489 | : [_] "{rdi}" (context), | ||
| 488 | [getContextInternal] "X" (&getContextInternal), | 490 | [getContextInternal] "X" (&getContextInternal), |
| 489 | : "memory", "rcx", "rdx", "rdi", "rsi", "r8", "r10", "r11" | 491 | : "cc", "memory", "rcx", "rdx", "rsi", "r8", "r10", "r11" |
| 490 | ); | 492 | ); |
| 491 | } | 493 | } |
lib/std/start.zig+22-22| ... | @@ -256,38 +256,38 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv | ... | @@ -256,38 +256,38 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv |
| 256 | fn _start() callconv(.Naked) noreturn { | 256 | fn _start() callconv(.Naked) noreturn { |
| 257 | switch (builtin.zig_backend) { | 257 | switch (builtin.zig_backend) { |
| 258 | .stage2_c => { | 258 | .stage2_c => { |
| 259 | @export(argc_argv_ptr, .{ .name = "argc_argv_ptr" }); | 259 | asm volatile (switch (native_arch) { |
| 260 | @export(posixCallMainAndExit, .{ .name = "_posixCallMainAndExit" }); | 260 | .x86_64 => |
| 261 | switch (native_arch) { | ||
| 262 | .x86_64 => asm volatile ( | ||
| 263 | \\ xorl %%ebp, %%ebp | 261 | \\ xorl %%ebp, %%ebp |
| 264 | \\ movq %%rsp, argc_argv_ptr | 262 | \\ movq %%rsp, %[argc_argv_ptr] |
| 265 | \\ andq $-16, %%rsp | 263 | \\ andq $-16, %%rsp |
| 266 | \\ call _posixCallMainAndExit | 264 | \\ callq %[posixCallMainAndExit:P] |
| 267 | ), | 265 | , |
| 268 | .x86 => asm volatile ( | 266 | .x86 => |
| 269 | \\ xorl %%ebp, %%ebp | 267 | \\ xorl %%ebp, %%ebp |
| 270 | \\ movl %%esp, argc_argv_ptr | 268 | \\ movl %%esp, %[argc_argv_ptr] |
| 271 | \\ andl $-16, %%esp | 269 | \\ andl $-16, %%esp |
| 272 | \\ jmp _posixCallMainAndExit | 270 | \\ calll %[posixCallMainAndExit:P] |
| 273 | ), | 271 | , |
| 274 | .aarch64, .aarch64_be => asm volatile ( | 272 | .aarch64, .aarch64_be => |
| 275 | \\ mov fp, #0 | 273 | \\ mov fp, #0 |
| 276 | \\ mov lr, #0 | 274 | \\ mov lr, #0 |
| 277 | \\ mov x0, sp | 275 | \\ mov x0, sp |
| 278 | \\ adrp x1, argc_argv_ptr | 276 | \\ str x0, %[argc_argv_ptr] |
| 279 | \\ str x0, [x1, :lo12:argc_argv_ptr] | 277 | \\ b %[posixCallMainAndExit] |
| 280 | \\ b _posixCallMainAndExit | 278 | , |
| 281 | ), | 279 | .arm, .armeb, .thumb => |
| 282 | .arm, .armeb, .thumb => asm volatile ( | ||
| 283 | \\ mov fp, #0 | 280 | \\ mov fp, #0 |
| 284 | \\ mov lr, #0 | 281 | \\ mov lr, #0 |
| 285 | \\ str sp, argc_argv_ptr | 282 | \\ str sp, %[argc_argv_ptr] |
| 286 | \\ and sp, #-16 | 283 | \\ and sp, #-16 |
| 287 | \\ b _posixCallMainAndExit | 284 | \\ b %[posixCallMainAndExit] |
| 288 | ), | 285 | , |
| 289 | else => @compileError("unsupported arch"), | 286 | else => @compileError("unsupported arch"), |
| 290 | } | 287 | } |
| 288 | : [argc_argv_ptr] "=m" (argc_argv_ptr), | ||
| 289 | : [posixCallMainAndExit] "X" (&posixCallMainAndExit), | ||
| 290 | ); | ||
| 291 | unreachable; | 291 | unreachable; |
| 292 | }, | 292 | }, |
| 293 | else => switch (native_arch) { | 293 | else => switch (native_arch) { |
src/codegen/c.zig+50-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 parameters | 34 | /// Index into the parameters |
| 35 | arg: usize, | 35 | arg: usize, |
| 36 | /// The array field of a parameter | 36 | /// 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() }; |
| 306 | 306 | ||
| 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 { |
| 352 | 352 | ||
| 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 | } |
| 365 | 365 | ||
| 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 | } |
| 379 | 381 | ||
| 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 | } |
| 393 | 397 | ||
| 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 | } |
| 408 | 414 | ||
| ... | @@ -4763,11 +4769,20 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4763,11 +4769,20 @@ fn airSwitchBr(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4763 | return .none; | 4769 | return .none; |
| 4764 | } | 4770 | } |
| 4765 | 4771 | ||
| 4766 | fn asmInputNeedsLocal(constraint: []const u8, value: CValue) bool { | 4772 | fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { |
| 4767 | return switch (constraint[0]) { | 4773 | return switch (constraint[0]) { |
| 4768 | '{' => true, | 4774 | '{' => true, |
| 4769 | 'i', 'r' => false, | 4775 | 'i', 'r' => false, |
| 4770 | else => value == .constant, | 4776 | else => switch (value) { |
| 4777 | .constant => |val| switch (f.object.dg.module.intern_pool.indexToKey(val)) { | ||
| 4778 | .ptr => |ptr| switch (ptr.addr) { | ||
| 4779 | .decl => false, | ||
| 4780 | else => true, | ||
| 4781 | }, | ||
| 4782 | else => true, | ||
| 4783 | }, | ||
| 4784 | else => false, | ||
| 4785 | }, | ||
| 4771 | }; | 4786 | }; |
| 4772 | } | 4787 | } |
| 4773 | 4788 | ||
| ... | @@ -4848,7 +4863,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4848,7 +4863,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4848 | 4863 | ||
| 4849 | const is_reg = constraint[0] == '{'; | 4864 | const is_reg = constraint[0] == '{'; |
| 4850 | const input_val = try f.resolveInst(input); | 4865 | const input_val = try f.resolveInst(input); |
| 4851 | if (asmInputNeedsLocal(constraint, input_val)) { | 4866 | if (asmInputNeedsLocal(f, constraint, input_val)) { |
| 4852 | const input_ty = f.typeOf(input); | 4867 | const input_ty = f.typeOf(input); |
| 4853 | if (is_reg) try writer.writeAll("register "); | 4868 | if (is_reg) try writer.writeAll("register "); |
| 4854 | const alignment = 0; | 4869 | const alignment = 0; |
| ... | @@ -4969,7 +4984,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { | ... | @@ -4969,7 +4984,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4969 | const is_reg = constraint[0] == '{'; | 4984 | const is_reg = constraint[0] == '{'; |
| 4970 | const input_val = try f.resolveInst(input); | 4985 | const input_val = try f.resolveInst(input); |
| 4971 | try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)}); | 4986 | try writer.print("{s}(", .{fmtStringLiteral(if (is_reg) "r" else constraint, null)}); |
| 4972 | try f.writeCValue(writer, if (asmInputNeedsLocal(constraint, input_val)) local: { | 4987 | try f.writeCValue(writer, if (asmInputNeedsLocal(f, constraint, input_val)) local: { |
| 4973 | const input_local = .{ .local = locals_index }; | 4988 | const input_local = .{ .local = locals_index }; |
| 4974 | locals_index += 1; | 4989 | locals_index += 1; |
| 4975 | break :local input_local; | 4990 | break :local input_local; |
test/behavior/fn.zig+1| ... | @@ -151,6 +151,7 @@ fn fnWithUnreachable() noreturn { | ... | @@ -151,6 +151,7 @@ fn fnWithUnreachable() noreturn { |
| 151 | 151 | ||
| 152 | test "extern struct with stdcallcc fn pointer" { | 152 | test "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; |
| 155 | 156 | ||
| 156 | const S = extern struct { | 157 | const S = extern struct { |
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 linux | 1053 | // 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 darwin | 1059 | // TODO stop violating these pedantic errors. spotted on darwin |