Index: lib/builtins/CMakeLists.txt =================================================================== --- lib/builtins/CMakeLists.txt +++ lib/builtins/CMakeLists.txt @@ -152,6 +152,7 @@ x86_64/floatundidf.S x86_64/floatundisf.S x86_64/floatundixf.S + x86_64/probestack.S ${GENERIC_SOURCES}) if(WIN32) @@ -173,6 +174,7 @@ i386/lshrdi3.S i386/moddi3.S i386/muldi3.S + i386/probestack.S i386/udivdi3.S i386/umoddi3.S ${GENERIC_SOURCES}) Index: lib/builtins/README.txt =================================================================== --- lib/builtins/README.txt +++ lib/builtins/README.txt @@ -196,6 +196,14 @@ // Runtime support +// __probestack() is used to touch all pages of `size` bytes which will +// later be allocated relative to the call site's stack pointer. It assumes +// that the first and the last byte after the allocation will be touched by +// something else. It has a custom platform specific calling convention. +// This function is not available on Windows platforms as those have their +// own builtins. +void __probestack(du_int size); + // __clear_cache() is used to tell process that new instructions have been // written to an address range. Necessary on processors that do not have // a unified instruction and data cache. Index: lib/builtins/i386/probestack.S =================================================================== --- /dev/null +++ lib/builtins/i386/probestack.S @@ -0,0 +1,58 @@ +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. + +#include "../assembly.h" + +// du_int __probestack(du_int size, du_int guard_size); + +// `size` is passed in eax, `guard_size` is passed in ebx, +// and this does not clobber any registers but eax. +// `size` is returned in eax aligned up to 4 bytes. + +#ifndef __WIN32__ +#ifdef __i386__ + +#if defined(__APPLE__) + .const +#elif defined(__ELF__) + .section .rodata +#else + .section .rdata,"rd" +#endif + +.text +.balign 4 +DEFINE_COMPILERRT_FUNCTION(__probestack) +.cfi_startproc + // Align size to 4 bytes + addl $3, %eax + andl $-4, %eax + + pushl %eax +.cfi_adjust_cfa_offset 4 +.cfi_rel_offset %eax, 0 + pushl %ecx +.cfi_adjust_cfa_offset 4 +.cfi_rel_offset %ecx, 0 + + // Load the pre-call ESP into ECX + leal 12(%esp), %ecx + +1: + subl %ebx, %ecx + orb $0, (%ecx) + subl %ebx, %eax + ja 1b + + popl %ecx +.cfi_adjust_cfa_offset -4 +.cfi_restore %ecx + popl %eax +.cfi_adjust_cfa_offset -4 +.cfi_restore %eax + ret +.cfi_endproc +END_COMPILERRT_FUNCTION(__probestack) + +#endif // __i386__ +#endif // __WIN32__ Index: lib/builtins/x86_64/probestack.S =================================================================== --- /dev/null +++ lib/builtins/x86_64/probestack.S @@ -0,0 +1,58 @@ +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. + +#include "../assembly.h" + +// du_int __probestack(du_int size, du_int guard_size); + +// `size` is passed in rax, `guard_size` is passed in rbx, +// and this does not clobber any registers but rax. +// `size` is returned in rax aligned up to 16 bytes. + +#ifndef __WIN32__ +#ifdef __x86_64__ + +#if defined(__APPLE__) + .const +#elif defined(__ELF__) + .section .rodata +#else + .section .rdata,"rd" +#endif + +.text +.balign 4 +DEFINE_COMPILERRT_FUNCTION(__probestack) +.cfi_startproc + // Align size to 16 bytes + addq $15, %rax + andq $-16, %rax + + pushq %rax +.cfi_adjust_cfa_offset 8 +.cfi_rel_offset %rax, 0 + pushq %r11 +.cfi_adjust_cfa_offset 8 +.cfi_rel_offset %r11, 0 + + // Load the pre-call RSP into R11 + leaq 24(%rsp), %r11 + +1: + subq %rbx, %r11 + orb $0, (%r11) + subq %rbx, %rax + ja 1b + + popq %r11 +.cfi_adjust_cfa_offset -8 +.cfi_restore %r11 + popq %rax +.cfi_adjust_cfa_offset -8 +.cfi_restore %rax + ret +.cfi_endproc +END_COMPILERRT_FUNCTION(__probestack) + +#endif // __x86_64__ +#endif // __WIN32__