| author | |
| committer | |
| log | be7cacfbbec8aed234a0316d11a9ae0e8cda0286 |
| tree | 65e070e9954eb8bfe7dbc95a4069d7f8fafe20ec |
| parent | 24ee7653184e6fbac0d05227723ddff2d716a28a |
Enabled on non-Windows systems only since it already requires stack
probes.5 files changed, 239 insertions(+), 110 deletions(-)
CMakeLists.txt+1| ... | @@ -644,6 +644,7 @@ set(ZIG_STD_FILES | ... | @@ -644,6 +644,7 @@ set(ZIG_STD_FILES |
| 644 | "special/build_runner.zig" | 644 | "special/build_runner.zig" |
| 645 | "special/builtin.zig" | 645 | "special/builtin.zig" |
| 646 | "special/compiler_rt.zig" | 646 | "special/compiler_rt.zig" |
| 647 | "special/compiler_rt/stack_probe.zig" | ||
| 647 | "special/compiler_rt/arm/aeabi_fcmp.zig" | 648 | "special/compiler_rt/arm/aeabi_fcmp.zig" |
| 648 | "special/compiler_rt/arm/aeabi_dcmp.zig" | 649 | "special/compiler_rt/arm/aeabi_dcmp.zig" |
| 649 | "special/compiler_rt/addXf3.zig" | 650 | "special/compiler_rt/addXf3.zig" |
src/codegen.cpp+11| ... | @@ -399,6 +399,15 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { | ... | @@ -399,6 +399,15 @@ static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { |
| 399 | } | 399 | } |
| 400 | } | 400 | } |
| 401 | 401 | ||
| 402 | static void add_probe_stack_attr(CodeGen *g, LLVMValueRef fn_val) { | ||
| 403 | // Windows already emits its own stack probes | ||
| 404 | if (g->zig_target->os != OsWindows && | ||
| 405 | (g->zig_target->arch == ZigLLVM_x86 || | ||
| 406 | g->zig_target->arch == ZigLLVM_x86_64)) { | ||
| 407 | addLLVMFnAttrStr(fn_val, "probe-stack", "__zig_probe_stack"); | ||
| 408 | } | ||
| 409 | } | ||
| 410 | |||
| 402 | static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { | 411 | static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { |
| 403 | switch (id) { | 412 | switch (id) { |
| 404 | case GlobalLinkageIdInternal: | 413 | case GlobalLinkageIdInternal: |
| ... | @@ -587,6 +596,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { | ... | @@ -587,6 +596,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { |
| 587 | addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong"); | 596 | addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong"); |
| 588 | addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4"); | 597 | addLLVMFnAttrStr(fn_table_entry->llvm_value, "stack-protector-buffer-size", "4"); |
| 589 | } | 598 | } |
| 599 | |||
| 600 | add_probe_stack_attr(g, fn_table_entry->llvm_value); | ||
| 590 | } | 601 | } |
| 591 | } else { | 602 | } else { |
| 592 | maybe_import_dll(g, fn_table_entry->llvm_value, linkage); | 603 | maybe_import_dll(g, fn_table_entry->llvm_value, linkage); |
src/main.cpp+6| ... | @@ -18,6 +18,12 @@ | ... | @@ -18,6 +18,12 @@ |
| 18 | 18 | ||
| 19 | #include <stdio.h> | 19 | #include <stdio.h> |
| 20 | 20 | ||
| 21 | // Define this symbol here so that we can link with the zig objects during the | ||
| 22 | // compiler bootstrap phase | ||
| 23 | extern "C" { | ||
| 24 | void __zig_probe_stack(void) { } | ||
| 25 | } | ||
| 26 | |||
| 21 | static int print_error_usage(const char *arg0) { | 27 | static int print_error_usage(const char *arg0) { |
| 22 | fprintf(stderr, "See `%s --help` for detailed usage information\n", arg0); | 28 | fprintf(stderr, "See `%s --help` for detailed usage information\n", arg0); |
| 23 | return EXIT_FAILURE; | 29 | return EXIT_FAILURE; |
std/special/compiler_rt.zig+15-110| ... | @@ -1,10 +1,17 @@ | ... | @@ -1,10 +1,17 @@ |
| 1 | const builtin = @import("builtin"); | 1 | const builtin = @import("builtin"); |
| 2 | const is_test = builtin.is_test; | 2 | const is_test = builtin.is_test; |
| 3 | 3 | ||
| 4 | const stack_probe = @import("compiler_rt/stack_probe.zig"); | ||
| 5 | |||
| 4 | comptime { | 6 | comptime { |
| 5 | const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak; | 7 | const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak; |
| 6 | const strong_linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong; | 8 | const strong_linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Strong; |
| 7 | 9 | ||
| 10 | switch (builtin.arch) { | ||
| 11 | .i386, .x86_64 => @export("__zig_probe_stack", @import("compiler_rt/stack_probe.zig").zig_probe_stack, linkage), | ||
| 12 | else => { } | ||
| 13 | } | ||
| 14 | |||
| 8 | @export("__lesf2", @import("compiler_rt/comparesf2.zig").__lesf2, linkage); | 15 | @export("__lesf2", @import("compiler_rt/comparesf2.zig").__lesf2, linkage); |
| 9 | @export("__ledf2", @import("compiler_rt/comparedf2.zig").__ledf2, linkage); | 16 | @export("__ledf2", @import("compiler_rt/comparedf2.zig").__ledf2, linkage); |
| 10 | @export("__letf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage); | 17 | @export("__letf2", @import("compiler_rt/comparetf2.zig").__letf2, linkage); |
| ... | @@ -191,20 +198,20 @@ comptime { | ... | @@ -191,20 +198,20 @@ comptime { |
| 191 | @export("__aeabi_dcmpun", @import("compiler_rt/comparedf2.zig").__unorddf2, linkage); | 198 | @export("__aeabi_dcmpun", @import("compiler_rt/comparedf2.zig").__unorddf2, linkage); |
| 192 | } | 199 | } |
| 193 | if (builtin.os == builtin.Os.windows) { | 200 | if (builtin.os == builtin.Os.windows) { |
| 201 | if (!builtin.link_libc) { | ||
| 202 | @export("_chkstk", @import("compiler_rt/stack_probe.zig")._chkstk, strong_linkage); | ||
| 203 | @export("__chkstk", @import("compiler_rt/stack_probe.zig").__chkstk, strong_linkage); | ||
| 204 | @export("___chkstk", @import("compiler_rt/stack_probe.zig").___chkstk, strong_linkage); | ||
| 205 | @export("__chkstk_ms", @import("compiler_rt/stack_probe.zig").__chkstk_ms, strong_linkage); | ||
| 206 | @export("___chkstk_ms", @import("compiler_rt/stack_probe.zig").___chkstk_ms, strong_linkage); | ||
| 207 | } | ||
| 208 | |||
| 194 | switch (builtin.arch) { | 209 | switch (builtin.arch) { |
| 195 | builtin.Arch.i386 => { | 210 | builtin.Arch.i386 => { |
| 196 | if (!builtin.link_libc) { | ||
| 197 | @export("_chkstk", _chkstk, strong_linkage); | ||
| 198 | @export("__chkstk_ms", __chkstk_ms, linkage); | ||
| 199 | } | ||
| 200 | @export("_aulldiv", @import("compiler_rt/aulldiv.zig")._aulldiv, strong_linkage); | 211 | @export("_aulldiv", @import("compiler_rt/aulldiv.zig")._aulldiv, strong_linkage); |
| 201 | @export("_aullrem", @import("compiler_rt/aullrem.zig")._aullrem, strong_linkage); | 212 | @export("_aullrem", @import("compiler_rt/aullrem.zig")._aullrem, strong_linkage); |
| 202 | }, | 213 | }, |
| 203 | builtin.Arch.x86_64 => { | 214 | builtin.Arch.x86_64 => { |
| 204 | if (!builtin.link_libc) { | ||
| 205 | @export("__chkstk", __chkstk, strong_linkage); | ||
| 206 | @export("___chkstk_ms", ___chkstk_ms, linkage); | ||
| 207 | } | ||
| 208 | // The "ti" functions must use @Vector(2, u64) parameter types to adhere to the ABI | 215 | // The "ti" functions must use @Vector(2, u64) parameter types to adhere to the ABI |
| 209 | // that LLVM expects compiler-rt to have. | 216 | // that LLVM expects compiler-rt to have. |
| 210 | @export("__divti3", @import("compiler_rt/divti3.zig").__divti3_windows_x86_64, linkage); | 217 | @export("__divti3", @import("compiler_rt/divti3.zig").__divti3_windows_x86_64, linkage); |
| ... | @@ -492,108 +499,6 @@ nakedcc fn __aeabi_memcmp() noreturn { | ... | @@ -492,108 +499,6 @@ nakedcc fn __aeabi_memcmp() noreturn { |
| 492 | unreachable; | 499 | unreachable; |
| 493 | } | 500 | } |
| 494 | 501 | ||
| 495 | // _chkstk (_alloca) routine - probe stack between %esp and (%esp-%eax) in 4k increments, | ||
| 496 | // then decrement %esp by %eax. Preserves all registers except %esp and flags. | ||
| 497 | // This routine is windows specific | ||
| 498 | // http://msdn.microsoft.com/en-us/library/ms648426.aspx | ||
| 499 | nakedcc fn _chkstk() align(4) void { | ||
| 500 | @setRuntimeSafety(false); | ||
| 501 | |||
| 502 | asm volatile ( | ||
| 503 | \\ push %%ecx | ||
| 504 | \\ push %%eax | ||
| 505 | \\ cmp $0x1000,%%eax | ||
| 506 | \\ lea 12(%%esp),%%ecx | ||
| 507 | \\ jb 1f | ||
| 508 | \\ 2: | ||
| 509 | \\ sub $0x1000,%%ecx | ||
| 510 | \\ test %%ecx,(%%ecx) | ||
| 511 | \\ sub $0x1000,%%eax | ||
| 512 | \\ cmp $0x1000,%%eax | ||
| 513 | \\ ja 2b | ||
| 514 | \\ 1: | ||
| 515 | \\ sub %%eax,%%ecx | ||
| 516 | \\ test %%ecx,(%%ecx) | ||
| 517 | \\ pop %%eax | ||
| 518 | \\ pop %%ecx | ||
| 519 | \\ ret | ||
| 520 | ); | ||
| 521 | } | ||
| 522 | |||
| 523 | nakedcc fn __chkstk() align(4) void { | ||
| 524 | @setRuntimeSafety(false); | ||
| 525 | |||
| 526 | asm volatile ( | ||
| 527 | \\ push %%rcx | ||
| 528 | \\ push %%rax | ||
| 529 | \\ cmp $0x1000,%%rax | ||
| 530 | \\ lea 24(%%rsp),%%rcx | ||
| 531 | \\ jb 1f | ||
| 532 | \\2: | ||
| 533 | \\ sub $0x1000,%%rcx | ||
| 534 | \\ test %%rcx,(%%rcx) | ||
| 535 | \\ sub $0x1000,%%rax | ||
| 536 | \\ cmp $0x1000,%%rax | ||
| 537 | \\ ja 2b | ||
| 538 | \\1: | ||
| 539 | \\ sub %%rax,%%rcx | ||
| 540 | \\ test %%rcx,(%%rcx) | ||
| 541 | \\ pop %%rax | ||
| 542 | \\ pop %%rcx | ||
| 543 | \\ ret | ||
| 544 | ); | ||
| 545 | } | ||
| 546 | |||
| 547 | // _chkstk routine | ||
| 548 | // This routine is windows specific | ||
| 549 | // http://msdn.microsoft.com/en-us/library/ms648426.aspx | ||
| 550 | nakedcc fn __chkstk_ms() align(4) void { | ||
| 551 | @setRuntimeSafety(false); | ||
| 552 | |||
| 553 | asm volatile ( | ||
| 554 | \\ push %%ecx | ||
| 555 | \\ push %%eax | ||
| 556 | \\ cmp $0x1000,%%eax | ||
| 557 | \\ lea 12(%%esp),%%ecx | ||
| 558 | \\ jb 1f | ||
| 559 | \\ 2: | ||
| 560 | \\ sub $0x1000,%%ecx | ||
| 561 | \\ test %%ecx,(%%ecx) | ||
| 562 | \\ sub $0x1000,%%eax | ||
| 563 | \\ cmp $0x1000,%%eax | ||
| 564 | \\ ja 2b | ||
| 565 | \\ 1: | ||
| 566 | \\ sub %%eax,%%ecx | ||
| 567 | \\ test %%ecx,(%%ecx) | ||
| 568 | \\ pop %%eax | ||
| 569 | \\ pop %%ecx | ||
| 570 | \\ ret | ||
| 571 | ); | ||
| 572 | } | ||
| 573 | |||
| 574 | nakedcc fn ___chkstk_ms() align(4) void { | ||
| 575 | @setRuntimeSafety(false); | ||
| 576 | |||
| 577 | asm volatile ( | ||
| 578 | \\ push %%rcx | ||
| 579 | \\ push %%rax | ||
| 580 | \\ cmp $0x1000,%%rax | ||
| 581 | \\ lea 24(%%rsp),%%rcx | ||
| 582 | \\ jb 1f | ||
| 583 | \\2: | ||
| 584 | \\ sub $0x1000,%%rcx | ||
| 585 | \\ test %%rcx,(%%rcx) | ||
| 586 | \\ sub $0x1000,%%rax | ||
| 587 | \\ cmp $0x1000,%%rax | ||
| 588 | \\ ja 2b | ||
| 589 | \\1: | ||
| 590 | \\ sub %%rax,%%rcx | ||
| 591 | \\ test %%rcx,(%%rcx) | ||
| 592 | \\ pop %%rax | ||
| 593 | \\ pop %%rcx | ||
| 594 | \\ ret | ||
| 595 | ); | ||
| 596 | } | ||
| 597 | 502 | ||
| 598 | extern fn __divmodsi4(a: i32, b: i32, rem: *i32) i32 { | 503 | extern fn __divmodsi4(a: i32, b: i32, rem: *i32) i32 { |
| 599 | @setRuntimeSafety(is_test); | 504 | @setRuntimeSafety(is_test); |
std/special/compiler_rt/stack_probe.zig created+206| ... | @@ -0,0 +1,206 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | |||
| 3 | // Zig's own stack-probe routine (available only on x86 and x86_64) | ||
| 4 | pub nakedcc fn zig_probe_stack() void { | ||
| 5 | @setRuntimeSafety(false); | ||
| 6 | |||
| 7 | // Versions of the Linux kernel before 5.1 treat any access below SP as | ||
| 8 | // invalid so let's update it on the go, otherwise we'll get a segfault | ||
| 9 | // instead of triggering the stack growth. | ||
| 10 | |||
| 11 | switch (builtin.arch) { | ||
| 12 | .x86_64 => { | ||
| 13 | // %rax = probe length, %rsp = stack pointer | ||
| 14 | asm volatile ( | ||
| 15 | \\ push %%rcx | ||
| 16 | \\ mov %%rax, %%rcx | ||
| 17 | \\ cmp $0x1000,%%rcx | ||
| 18 | \\ jb 2f | ||
| 19 | \\ 1: | ||
| 20 | \\ sub $0x1000,%%rsp | ||
| 21 | \\ orl $0,16(%%rsp) | ||
| 22 | \\ sub $0x1000,%%rcx | ||
| 23 | \\ cmp $0x1000,%%rcx | ||
| 24 | \\ ja 1b | ||
| 25 | \\ 2: | ||
| 26 | \\ sub %%rcx, %%rsp | ||
| 27 | \\ orl $0,16(%%rsp) | ||
| 28 | \\ add %%rax,%%rsp | ||
| 29 | \\ pop %%rcx | ||
| 30 | \\ ret | ||
| 31 | ); | ||
| 32 | }, | ||
| 33 | .i386 => { | ||
| 34 | // %eax = probe length, %esp = stack pointer | ||
| 35 | asm volatile ( | ||
| 36 | \\ push %%ecx | ||
| 37 | \\ mov %%eax, %%ecx | ||
| 38 | \\ cmp $0x1000,%%ecx | ||
| 39 | \\ jb 2f | ||
| 40 | \\ 1: | ||
| 41 | \\ sub $0x1000,%%esp | ||
| 42 | \\ orl $0,8(%%esp) | ||
| 43 | \\ sub $0x1000,%%ecx | ||
| 44 | \\ cmp $0x1000,%%ecx | ||
| 45 | \\ ja 1b | ||
| 46 | \\ 2: | ||
| 47 | \\ sub %%ecx, %%esp | ||
| 48 | \\ orl $0,8(%%esp) | ||
| 49 | \\ add %%eax,%%esp | ||
| 50 | \\ pop %%ecx | ||
| 51 | \\ ret | ||
| 52 | ); | ||
| 53 | }, | ||
| 54 | else => { } | ||
| 55 | } | ||
| 56 | |||
| 57 | unreachable; | ||
| 58 | } | ||
| 59 | |||
| 60 | fn win_probe_stack_only() void { | ||
| 61 | @setRuntimeSafety(false); | ||
| 62 | |||
| 63 | switch (builtin.arch) { | ||
| 64 | .x86_64 => { | ||
| 65 | asm volatile ( | ||
| 66 | \\ push %%rcx | ||
| 67 | \\ push %%rax | ||
| 68 | \\ cmp $0x1000,%%rax | ||
| 69 | \\ lea 24(%%rsp),%%rcx | ||
| 70 | \\ jb 1f | ||
| 71 | \\ 2: | ||
| 72 | \\ sub $0x1000,%%rcx | ||
| 73 | \\ test %%rcx,(%%rcx) | ||
| 74 | \\ sub $0x1000,%%rax | ||
| 75 | \\ cmp $0x1000,%%rax | ||
| 76 | \\ ja 2b | ||
| 77 | \\ 1: | ||
| 78 | \\ sub %%rax,%%rcx | ||
| 79 | \\ test %%rcx,(%%rcx) | ||
| 80 | \\ pop %%rax | ||
| 81 | \\ pop %%rcx | ||
| 82 | \\ ret | ||
| 83 | ); | ||
| 84 | }, | ||
| 85 | .i386 => { | ||
| 86 | asm volatile ( | ||
| 87 | \\ push %%ecx | ||
| 88 | \\ push %%eax | ||
| 89 | \\ cmp $0x1000,%%eax | ||
| 90 | \\ lea 12(%%esp),%%ecx | ||
| 91 | \\ jb 1f | ||
| 92 | \\ 2: | ||
| 93 | \\ sub $0x1000,%%ecx | ||
| 94 | \\ test %%ecx,(%%ecx) | ||
| 95 | \\ sub $0x1000,%%eax | ||
| 96 | \\ cmp $0x1000,%%eax | ||
| 97 | \\ ja 2b | ||
| 98 | \\ 1: | ||
| 99 | \\ sub %%eax,%%ecx | ||
| 100 | \\ test %%ecx,(%%ecx) | ||
| 101 | \\ pop %%eax | ||
| 102 | \\ pop %%ecx | ||
| 103 | \\ ret | ||
| 104 | ); | ||
| 105 | }, | ||
| 106 | else => { } | ||
| 107 | } | ||
| 108 | |||
| 109 | unreachable; | ||
| 110 | } | ||
| 111 | |||
| 112 | fn win_probe_stack_adjust_sp() void { | ||
| 113 | @setRuntimeSafety(false); | ||
| 114 | |||
| 115 | switch (builtin.arch) { | ||
| 116 | .x86_64 => { | ||
| 117 | asm volatile ( | ||
| 118 | \\ push %%rcx | ||
| 119 | \\ cmp $0x1000,%%rax | ||
| 120 | \\ lea 16(%%rsp),%%rcx | ||
| 121 | \\ jb 1f | ||
| 122 | \\ 2: | ||
| 123 | \\ sub $0x1000,%%rcx | ||
| 124 | \\ test %%rcx,(%%rcx) | ||
| 125 | \\ sub $0x1000,%%rax | ||
| 126 | \\ cmp $0x1000,%%rax | ||
| 127 | \\ ja 2b | ||
| 128 | \\ 1: | ||
| 129 | \\ sub %%rax,%%rcx | ||
| 130 | \\ test %%rcx,(%%rcx) | ||
| 131 | \\ | ||
| 132 | \\ lea 8(%%rsp),%%rax | ||
| 133 | \\ mov %%rcx,%%rsp | ||
| 134 | \\ mov -8(%%rax),%%rcx | ||
| 135 | \\ push (%%rax) | ||
| 136 | \\ sub %%rsp,%%rax | ||
| 137 | \\ ret | ||
| 138 | ); | ||
| 139 | }, | ||
| 140 | .i386 => { | ||
| 141 | asm volatile ( | ||
| 142 | \\ push %%ecx | ||
| 143 | \\ cmp $0x1000,%%eax | ||
| 144 | \\ lea 8(%%esp),%%ecx | ||
| 145 | \\ jb 1f | ||
| 146 | \\ 2: | ||
| 147 | \\ sub $0x1000,%%ecx | ||
| 148 | \\ test %%ecx,(%%ecx) | ||
| 149 | \\ sub $0x1000,%%eax | ||
| 150 | \\ cmp $0x1000,%%eax | ||
| 151 | \\ ja 2b | ||
| 152 | \\ 1: | ||
| 153 | \\ sub %%eax,%%ecx | ||
| 154 | \\ test %%ecx,(%%ecx) | ||
| 155 | \\ | ||
| 156 | \\ lea 4(%%esp),%%eax | ||
| 157 | \\ mov %%ecx,%%esp | ||
| 158 | \\ mov -4(%%eax),%%ecx | ||
| 159 | \\ push (%%eax) | ||
| 160 | \\ sub %%esp,%%eax | ||
| 161 | \\ ret | ||
| 162 | ); | ||
| 163 | }, | ||
| 164 | else => { }, | ||
| 165 | } | ||
| 166 | |||
| 167 | unreachable; | ||
| 168 | } | ||
| 169 | |||
| 170 | // Windows has a multitude of stack-probing functions with similar names and | ||
| 171 | // slightly different behaviours: some behave as alloca() and update the stack | ||
| 172 | // pointer after probing the stack, other do not. | ||
| 173 | // | ||
| 174 | // Function name | Adjusts the SP? | | ||
| 175 | // | x86 | x86_64 | | ||
| 176 | // ---------------------------------------- | ||
| 177 | // _chkstk (_alloca) | yes | yes | | ||
| 178 | // __chkstk | yes | no | | ||
| 179 | // __chkstk_ms | no | no | | ||
| 180 | // ___chkstk (__alloca) | yes | yes | | ||
| 181 | // ___chkstk_ms | no | no | | ||
| 182 | |||
| 183 | pub nakedcc fn _chkstk() void { | ||
| 184 | @setRuntimeSafety(false); | ||
| 185 | @inlineCall(win_probe_stack_adjust_sp); | ||
| 186 | } | ||
| 187 | pub nakedcc fn __chkstk() void { | ||
| 188 | @setRuntimeSafety(false); | ||
| 189 | switch (builtin.arch) { | ||
| 190 | .i386 => @inlineCall(win_probe_stack_adjust_sp), | ||
| 191 | .x86_64 => @inlineCall(win_probe_stack_only), | ||
| 192 | else => unreachable | ||
| 193 | } | ||
| 194 | } | ||
| 195 | pub nakedcc fn ___chkstk() void { | ||
| 196 | @setRuntimeSafety(false); | ||
| 197 | @inlineCall(win_probe_stack_adjust_sp); | ||
| 198 | } | ||
| 199 | pub nakedcc fn __chkstk_ms() void { | ||
| 200 | @setRuntimeSafety(false); | ||
| 201 | @inlineCall(win_probe_stack_only); | ||
| 202 | } | ||
| 203 | pub nakedcc fn ___chkstk_ms() void { | ||
| 204 | @setRuntimeSafety(false); | ||
| 205 | @inlineCall(win_probe_stack_only); | ||
| 206 | } | ||