aboutsummaryrefslogtreecommitdiff
path: root/libphobos/libdruntime/config
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gdcproject.org>2021-04-19 14:48:32 +0200
committerIain Buclaw <ibuclaw@gdcproject.org>2021-04-19 19:27:27 +0200
commit6eae7549b8a350b92435be904efed195bd190bae (patch)
treecc4144e57ee31c6ef94edfe90b881cda17b25c13 /libphobos/libdruntime/config
parentb66e72b43e1e8f402dc958ce3cca35f7c273340d (diff)
downloadgcc-6eae7549b8a350b92435be904efed195bd190bae.zip
gcc-6eae7549b8a350b92435be904efed195bd190bae.tar.gz
gcc-6eae7549b8a350b92435be904efed195bd190bae.tar.bz2
libphobos: Add Thread/Fiber support code for Darwin (PR98058)
libphobos/ChangeLog: PR d/98058 * configure: Regenerate. * libdruntime/Makefile.am (DRUNTIME_DSOURCES_DARWIN): Add core/sys/darwin/config.d * libdruntime/Makefile.in: Regenerate. * libdruntime/config/powerpc/switchcontext.S: Implement fiber_switchContext for __MACH__. * libdruntime/config/x86/switchcontext.S: Likewise. * libdruntime/core/sys/darwin/config.d: New file. * libdruntime/core/thread/fiber.d (Fiber.getThis): Mark noinline. (UnsafeFiberMigration): Define for OSX/X86 and OSX/X86_64. * libdruntime/core/thread/osthread.d (callWithStackShell): Add inline assembler implementation for X86, X86_64, PPC, and PPC64. * libdruntime/core/thread/threadbase.d (ThreadBase.getThis): Mark noinline. * libdruntime/gcc/deh.d (FuncTable): Remove definition. * m4/druntime/os.m4 (DRUNTIME_OS_MINFO_BRACKETING): Check for right bracket symbol on darwin* targets. * testsuite/libphobos.thread/fiber_guard_page.d: Update test to support ucontext-based Fibers.
Diffstat (limited to 'libphobos/libdruntime/config')
-rw-r--r--libphobos/libdruntime/config/powerpc/switchcontext.S278
-rw-r--r--libphobos/libdruntime/config/x86/switchcontext.S159
2 files changed, 432 insertions, 5 deletions
diff --git a/libphobos/libdruntime/config/powerpc/switchcontext.S b/libphobos/libdruntime/config/powerpc/switchcontext.S
index d4ea577..74395b0 100644
--- a/libphobos/libdruntime/config/powerpc/switchcontext.S
+++ b/libphobos/libdruntime/config/powerpc/switchcontext.S
@@ -24,7 +24,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#include "../common/threadasm.S"
-#if !defined(__PPC64__)
+#if !defined(__PPC64__) && !defined(__MACH__)
/**
* Performs a context switch.
@@ -151,4 +151,278 @@ CSYM(fiber_switchContext):
.cfi_endproc
.size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
-#endif /* !defined(__PPC64__) */
+#elif defined(__MACH__)
+
+/* Implementation for Darwin/macOS preserving callee-saved regs.
+
+ FIXME : There is no unwind frame.
+ FIXME : not sure if we should save the vsave reg (perhaps using the slot we have
+ r11 in at present). */
+
+/* Darwin has a red zone (220 bytes for PPC 288 for PPC64) which we can write
+ to before the stack is updated without worrying about it being clobbered by
+ signals or hardware interrupts.
+
+ The stack will be 16byte aligned on entry with:
+ PPC PPC64
+ SP-> +---------------------------------------+
+ | back chain to caller | 0 0
+ +---------------------------------------+
+ | slot to save CR | 4 8
+ +---------------------------------------+
+ | slot to save LR | 8 16
+ +---------------------------------------+
+ | etc.. etc.. as per C calling conv. | */
+
+# if __PPC64__
+# define LD ld
+# define ST std
+# define STU stdu
+# define SZ 8
+# define MACHINE ppc64
+# define RED_ZONE 288
+# else
+# define LD lwz
+# define ST stw
+# define STU stwu
+# define SZ 4
+# define MACHINE ppc7400
+# define RED_ZONE 220
+# endif
+
+# define SAVE_VECTORS 0
+/**
+ * Performs a context switch.
+ *
+ * r3 - old context pointer
+ * r4 - new context pointer
+ *
+ */
+ .machine MACHINE
+ .text
+ .globl CSYM(fiber_switchContext)
+ .align 2
+CSYM(fiber_switchContext):
+LFB0:
+ /* Get the link reg. */
+ mflr r0
+ /* Get the callee-saved crs (well all of them, actually). */
+ mfcr r12
+
+ /* Save GPRs, we save the static chain here too although it is not clear if we need to. */
+ ST r31, ( -1 * SZ)(r1)
+ ST r30, ( -2 * SZ)(r1)
+ ST r29, ( -3 * SZ)(r1)
+ ST r28, ( -4 * SZ)(r1)
+ ST r27, ( -5 * SZ)(r1)
+ ST r26, ( -6 * SZ)(r1)
+ ST r25, ( -7 * SZ)(r1)
+ ST r24, ( -8 * SZ)(r1)
+ ST r23, ( -9 * SZ)(r1)
+ ST r22, (-10 * SZ)(r1)
+ ST r21, (-11 * SZ)(r1)
+ ST r20, (-12 * SZ)(r1)
+ ST r19, (-13 * SZ)(r1)
+ ST r18, (-14 * SZ)(r1)
+ ST r17, (-15 * SZ)(r1)
+ ST r16, (-16 * SZ)(r1)
+ ST r15, (-17 * SZ)(r1)
+ ST r14, (-18 * SZ)(r1)
+ ST r13, (-19 * SZ)(r1)
+
+ /* Save the lr and cr into the normal function linkage area. */
+ ST r0, 2*SZ(r1)
+ ST r12, SZ(r1)
+
+ /* We update the stack pointer here, since we do not want the GC to
+ scan the floating point registers. We are still 16-byte aligned. */
+ STU r11, (-20 * SZ)(r1)
+
+ /* Update the stack pointer in the old context as per comment above. */
+ ST r1, 0(r3)
+
+ /* Save FPRs - same for PPC and PPC64 */
+ stfd f14, (-18 * 8)(r1)
+ stfd f15, (-17 * 8)(r1)
+ stfd f16, (-16 * 8)(r1)
+ stfd f17, (-15 * 8)(r1)
+ stfd f18, (-14 * 8)(r1)
+ stfd f19, (-13 * 8)(r1)
+ stfd f20, (-12 * 8)(r1)
+ stfd f21, (-11 * 8)(r1)
+ stfd f22, (-10 * 8)(r1)
+ stfd f23, ( -9 * 8)(r1)
+ stfd f24, ( -8 * 8)(r1)
+ stfd f25, ( -7 * 8)(r1)
+ stfd f26, ( -6 * 8)(r1)
+ stfd f27, ( -5 * 8)(r1)
+ stfd f28, ( -4 * 8)(r1)
+ stfd f29, ( -3 * 8)(r1)
+ stfd f30, ( -2 * 8)(r1)
+ stfd f31, ( -1 * 8)(r1)
+
+#if SAVE_VECTORS
+ /* We are still 16byte aligned - so we are ok for vector saves.
+ but the combined size of the vectors (12 x 16) + the FPRs (144) exceeds the
+ red zone size so we need to adjust the stack again - note this means careful
+ ordering is needed on the restore. */
+
+ addi r1, r1, -(12*16+18*8)
+ li r11, 0
+ stvx v20,r11,r1
+ addi r11, r11, 16
+ stvx v21,r11,r1
+ addi r11, r11, 16
+ stvx v22,r11,r1
+ addi r11, r11, 16
+ stvx v23,r11,r1
+ addi r11, r11, 16
+ stvx v24,r11,r1
+ addi r11, r11, 16
+ stvx v25,r11,r1
+ addi r11, r11, 16
+ stvx v26,r11,r1
+ addi r11, r11, 16
+ stvx v27,r11,r1
+ addi r11, r11, 16
+ stvx v28,r11,r1
+ addi r11, r11, 16
+ stvx v29,r11,r1
+ addi r11, r11, 16
+ stvx v30,r11,r1
+ addi r11, r11, 16
+ stvx v31,r11,r1
+
+ /* Now do the same thing in reverse - starting with r4 pointing to
+ the block of GPRs - stage 1 point to the saved vectors and fprs. */
+
+ addi r1, r4, -(12*16+18*8)
+ li r11, 0
+ lvx v20,r11,r1
+ addi r11, r11, 16
+ lvx v21,r11,r1
+ addi r11, r11, 16
+ lvx v22,r11,r1
+ addi r11, r11, 16
+ lvx v23,r11,r1
+ addi r11, r11, 16
+ lvx v24,r11,r1
+ addi r11, r11, 16
+ lvx v25,r11,r1
+ addi r11, r11, 16
+ lvx v26,r11,r1
+ addi r11, r11, 16
+ lvx v27,r11,r1
+ addi r11, r11, 16
+ lvx v28,r11,r1
+ addi r11, r11, 16
+ lvx v29,r11,r1
+ addi r11, r11, 16
+ lvx v30,r11,r1
+ addi r11, r11, 16
+ lvx v31,r11,r1
+#endif
+
+ /* Now it is safe to update the stack pointer since the combined
+ size of the GPRs and FPRs will not exceed the red zone. */
+
+ addi r1, r4, 20 * SZ
+
+ /* Restore FPRs */
+ lfd f14, (-18 * 8)(r4)
+ lfd f15, (-17 * 8)(r4)
+ lfd f16, (-16 * 8)(r4)
+ lfd f17, (-15 * 8)(r4)
+ lfd f18, (-14 * 8)(r4)
+ lfd f19, (-13 * 8)(r4)
+ lfd f20, (-12 * 8)(r4)
+ lfd f21, (-11 * 8)(r4)
+ lfd f22, (-10 * 8)(r4)
+ lfd f23, ( -9 * 8)(r4)
+ lfd f24, ( -8 * 8)(r4)
+ lfd f25, ( -7 * 8)(r4)
+ lfd f26, ( -6 * 8)(r4)
+ lfd f27, ( -5 * 8)(r4)
+ lfd f28, ( -4 * 8)(r4)
+ lfd f29, ( -3 * 8)(r4)
+ lfd f30, ( -2 * 8)(r4)
+ lfd f31, ( -1 * 8)(r4)
+
+ /* Pick up lr and cr */
+ LD r0, 2*SZ(r1)
+ LD r12, SZ(r1)
+
+ /* Restore GPRs */
+ LD r11, (-20 * SZ)(r1)
+ LD r13, (-19 * SZ)(r1)
+ LD r14, (-18 * SZ)(r1)
+ LD r15, (-17 * SZ)(r1)
+ LD r16, (-16 * SZ)(r1)
+ LD r17, (-15 * SZ)(r1)
+ LD r18, (-14 * SZ)(r1)
+ LD r19, (-13 * SZ)(r1)
+ LD r20, (-12 * SZ)(r1)
+ LD r21, (-11 * SZ)(r1)
+ LD r22, (-10 * SZ)(r1)
+ LD r23, ( -9 * SZ)(r1)
+ LD r24, ( -8 * SZ)(r1)
+ LD r25, ( -7 * SZ)(r1)
+ LD r26, ( -6 * SZ)(r1)
+ LD r27, ( -5 * SZ)(r1)
+ LD r28, ( -4 * SZ)(r1)
+ LD r29, ( -3 * SZ)(r1)
+ LD r30, ( -2 * SZ)(r1)
+ LD r31, ( -1 * SZ)(r1)
+
+ /* Set cr and lr */
+ mtcr r12
+ mtlr r0
+
+ /* Return and switch context */
+ blr
+LFE0:
+
+/* Minimal CFI / FDE which does not describe the stacking of the GPRs - but only that
+ the routine has been entered/exited. */
+
+# if __PPC64__
+# define DATA_ALIGN 0x78
+# define ALIGN_SIZE 3
+# define ADDRD .quad
+# else
+# define DATA_ALIGN 0x7c
+# define ALIGN_SIZE 3
+# define ADDRD .long
+# endif
+
+ .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+ .set L$set$0,LECIE1-LSCIE1
+ .long L$set$0 ; Length of Common Information Entry
+LSCIE1:
+ .long 0 ; CIE Identifier Tag
+ .byte 0x3 ; CIE Version
+ .ascii "zR\0" ; CIE Augmentation
+ .byte 0x1 ; uleb128 0x1; CIE Code Alignment Factor
+ .byte DATA_ALIGN ; sleb128 -4/-8; CIE Data Alignment Factor
+ .byte 0x41 ; uleb128 0x41; CIE RA Column
+ .byte 0x1 ; uleb128 0x1; Augmentation size
+ .byte 0x10 ; FDE Encoding (pcrel)
+ .byte 0xc ; DW_CFA_def_cfa
+ .byte 0x1 ; uleb128 0x1
+ .byte 0 ; uleb128 0
+ .p2align ALIGN_SIZE,0
+LECIE1:
+LSFDE1:
+ .set L$set$1,LEFDE1-LASFDE1
+ .long L$set$1 ; FDE Length
+LASFDE1:
+ .long LASFDE1-EH_frame1 ; FDE CIE offset
+ ADDRD LFB0-. ; FDE initial location
+ .set L$set$2,LFE0-LFB0
+ ADDRD L$set$2 ; FDE address range
+ .byte 0 ; uleb128 0; Augmentation size
+ .p2align ALIGN_SIZE,0
+LEFDE1:
+
+#endif /* defined(__MACH__) */
diff --git a/libphobos/libdruntime/config/x86/switchcontext.S b/libphobos/libdruntime/config/x86/switchcontext.S
index 82420c6..9f4befd 100644
--- a/libphobos/libdruntime/config/x86/switchcontext.S
+++ b/libphobos/libdruntime/config/x86/switchcontext.S
@@ -29,7 +29,11 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
# include <cet.h>
#endif
-#if defined(__i386__) && !defined(__CET__)
+#if !defined(__CET__)
+
+# if defined(__ELF__)
+
+# if defined(__i386__)
.text
.globl CSYM(fiber_switchContext)
@@ -63,7 +67,9 @@ CSYM(fiber_switchContext):
.cfi_endproc
.size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
-#elif defined(__x86_64__) && !defined(__ILP32__) && !defined(__CET__)
+# endif /* defined(__ELF__) && defined(__i386__) */
+
+# if defined(__x86_64__) && !defined(__ILP32__)
.text
.globl CSYM(fiber_switchContext)
@@ -98,4 +104,151 @@ CSYM(fiber_switchContext):
.cfi_endproc
.size CSYM(fiber_switchContext),.-CSYM(fiber_switchContext)
-#endif
+# endif /* defined(__ELF__) && defined(__x86_64__) && !defined(__ILP32__) */
+
+# endif /* defined(__ELF__) */
+
+# if defined(__MACH__)
+
+# if defined(__i386__)
+
+ .text
+ .globl CSYM(fiber_switchContext)
+ .p2align 4
+CSYM(fiber_switchContext):
+LFB0:
+ // save current stack state
+ push %ebp
+ mov %esp, %ebp
+ push %edi
+ push %esi
+ push %ebx
+ push %eax
+
+ // store oldp again with more accurate address
+ mov 8(%ebp), %eax
+ mov %esp, (%eax)
+ // load newp to begin context switch
+ mov 12(%ebp), %esp
+
+ // load saved state from new stack
+ pop %eax
+ pop %ebx
+ pop %esi
+ pop %edi
+ pop %ebp
+
+ // 'return' to complete switch
+ ret
+LFE0:
+
+/* CFI */
+ .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+ .set L$set$0,LECIE1-LSCIE1
+ .long L$set$0 # Length of Common Information Entry
+LSCIE1:
+ .long 0 # CIE Identifier Tag
+ .byte 0x1 # CIE Version
+ .ascii "zR\0" # CIE Augmentation
+ .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
+ .byte 0x7c # sleb128 -4; CIE Data Alignment Factor
+ .byte 0x8 # CIE RA Column
+ .byte 0x1 # uleb128 0x1; Augmentation size
+ .byte 0x10 # FDE Encoding (pcrel)
+ .byte 0xc # DW_CFA_def_cfa
+ .byte 0x5 # uleb128 0x5
+ .byte 0x4 # uleb128 0x4
+ .byte 0x88 # DW_CFA_offset, column 0x8
+ .byte 0x1 # uleb128 0x1
+ .p2align 2,0
+LECIE1:
+
+/* minimal FDE - does not record the stack frame changes. */
+LSFDE1:
+ .set L$set$1,LEFDE1-LASFDE1
+ .long L$set$1 # FDE Length
+LASFDE1:
+ .long LASFDE1-EH_frame1 # FDE CIE offset
+ .long LFB0-. # FDE initial location
+ .set L$set$2,LFE0-LFB0
+ .long L$set$2 # FDE address range
+ .byte 0 # uleb128 0; Augmentation size
+ .p2align 2,0
+LEFDE1:
+
+# endif /* defined(__MACH__) && defined(__i386__) */
+
+# if defined(__x86_64__) && !defined(__ILP32__)
+
+ .text
+ .globl CSYM(fiber_switchContext)
+ .p2align 4
+CSYM(fiber_switchContext):
+LFB0:
+ // Save current stack state.save current stack state
+ push %rbp
+ mov %rsp, %rbp
+ push %r15
+ push %r14
+ push %r13
+ push %r12
+ push %rbx
+
+ // store oldp again with more accurate address
+ mov %rsp, (%rdi)
+ // load newp to begin context switch
+ mov %rsi, %rsp
+
+ // load saved state from new stack
+ pop %rbx
+ pop %r12
+ pop %r13
+ pop %r14
+ pop %r15
+ pop %rbp
+
+ // 'return' to complete switch
+ ret
+LFE0:
+
+/* CFI */
+ .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
+EH_frame1:
+ .set L$set$0,LECIE1-LSCIE1
+ .long L$set$0 # Length of Common Information Entry
+LSCIE1:
+ .long 0 # CIE Identifier Tag
+ .byte 0x1 # CIE Version
+ .ascii "zR\0" # CIE Augmentation
+ .byte 0x1 # uleb128 0x1; CIE Code Alignment Factor
+ .byte 0x78 # sleb128 -8; CIE Data Alignment Factor
+ .byte 0x10 # CIE RA Column
+ .byte 0x1 # uleb128 0x1; Augmentation size
+ .byte 0x10 # FDE Encoding (pcrel)
+ .byte 0xc # DW_CFA_def_cfa
+ .byte 0x7 # uleb128 0x7
+ .byte 0x8 # uleb128 0x8
+ .byte 0x90 # DW_CFA_offset, column 0x10
+ .byte 0x1 # uleb128 0x1
+ .p2align 3,0
+LECIE1:
+
+/* minimal FDE - does not record the stack frame changes. */
+LSFDE1:
+ .set L$set$1,LEFDE1-LASFDE1
+ .long L$set$1 # FDE Length
+LASFDE1:
+ .long LASFDE1-EH_frame1 # FDE CIE offset
+ .quad LFB0-. # FDE initial location
+ .set L$set$2,LFE0-LFB0
+ .quad L$set$2 # FDE address range
+ .byte 0 # uleb128 0; Augmentation size
+ .p2align 3,0
+LEFDE1:
+
+# endif /* defined(__MACH__) && defined(__x86_64__) && !defined(__ILP32__) */
+
+# endif /* defined (__MACH__) */
+
+#endif /* !defined(__CET__) */