Showing with 126 additions and 0 deletions.
  1. +2 −0 lib/builtins/CMakeLists.txt
  2. +8 −0 lib/builtins/README.txt
  3. +58 −0 lib/builtins/i386/probestack.S
  4. +58 −0 lib/builtins/x86_64/probestack.S
2 changes: 2 additions & 0 deletions lib/builtins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ set(x86_64_SOURCES
x86_64/floatundidf.S
x86_64/floatundisf.S
x86_64/floatundixf.S
x86_64/probestack.S
${GENERIC_SOURCES})

if(WIN32)
Expand All @@ -173,6 +174,7 @@ set(i386_SOURCES
i386/lshrdi3.S
i386/moddi3.S
i386/muldi3.S
i386/probestack.S
i386/udivdi3.S
i386/umoddi3.S
${GENERIC_SOURCES})
Expand Down
8 changes: 8 additions & 0 deletions lib/builtins/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,14 @@ long double _Complex __divtc3(long double a, long double b,

// 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.
Expand Down
58 changes: 58 additions & 0 deletions lib/builtins/i386/probestack.S
Original file line number Diff line number Diff line change
@@ -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__
58 changes: 58 additions & 0 deletions lib/builtins/x86_64/probestack.S
Original file line number Diff line number Diff line change
@@ -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__