Skip to content

Commit 567725e

Browse files
authored
Fix and improve coroutines for Darwin (macOS) ppc/ppc64. (ruby#5975)
1 parent fc3137e commit 567725e

File tree

17 files changed

+194
-118
lines changed

17 files changed

+194
-118
lines changed

addr2line.c

+4-1
Original file line numberDiff line numberDiff line change
@@ -869,8 +869,11 @@ typedef struct {
869869
int type;
870870
} DebugInfoValue;
871871

872-
/* TODO: Big Endian */
872+
#if defined(WORDS_BIGENDIAN)
873+
#define MERGE_2INTS(a,b,sz) (((uint64_t)(a)<<sz)|(b))
874+
#else
873875
#define MERGE_2INTS(a,b,sz) (((uint64_t)(b)<<sz)|(a))
876+
#endif
874877

875878
static uint16_t
876879
get_uint16(const uint8_t *p)

configure.ac

+7-4
Original file line numberDiff line numberDiff line change
@@ -1902,8 +1902,8 @@ AS_CASE(["${target_cpu}-${target_os}:${target_archs}"],
19021902
[universal-darwin*:*ppc*], [
19031903
AC_LIBSOURCES(alloca.c)
19041904
AC_SUBST([ALLOCA], [\${LIBOBJDIR}alloca.${ac_objext}])
1905-
RUBY_DEFINE_IF([defined __powerpc__], C_ALLOCA, 1)
1906-
RUBY_DEFINE_IF([defined __powerpc__], alloca, alloca)
1905+
RUBY_DEFINE_IF([defined __POWERPC__], C_ALLOCA, 1) # Darwin defines __POWERPC__ for ppc and ppc64 both
1906+
RUBY_DEFINE_IF([defined __POWERPC__], alloca, alloca)
19071907
],
19081908
[
19091909
AC_FUNC_ALLOCA
@@ -2573,10 +2573,13 @@ AS_CASE([$coroutine_type], [yes|''], [
25732573
[arm64-darwin*], [
25742574
coroutine_type=arm64
25752575
],
2576-
[powerpc-darwin*], [
2576+
# Correct target name is powerpc*-, but Ruby seems to prefer ppc*-.
2577+
# Notice that Darwin PPC ABI differs from AIX and ELF.
2578+
# Adding PPC targets for AIX, *BSD and *Linux will require separate implementations.
2579+
[powerpc-darwin*|ppc-darwin*], [
25772580
coroutine_type=ppc
25782581
],
2579-
[powerpc64-darwin*], [
2582+
[powerpc64-darwin*|ppc64-darwin*], [
25802583
coroutine_type=ppc64
25812584
],
25822585
[x*64-linux*], [

coroutine/ppc/Context.S

+67-50
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,90 @@
1+
; Based on the code by Samuel Williams. Created by Sergey Fedorov on 04/06/2022.
2+
; Credits to Samuel Williams, Rei Odaira and Iain Sandoe. Errors, if any, are mine.
3+
; Some relevant examples: https://github.com/gcc-mirror/gcc/blob/master/libphobos/libdruntime/config/powerpc/switchcontext.S
4+
; https://github.com/gcc-mirror/gcc/blob/master/libgcc/config/rs6000/darwin-gpsave.S
5+
; https://www.ibm.com/docs/en/aix/7.2?topic=epilogs-saving-gprs-only
6+
; ppc32 version may be re-written compactly with stmw/lwm, but the code wonʼt be faster, see: https://github.com/ruby/ruby/pull/5927#issuecomment-1139730541
7+
8+
; Notice that this code is only for Darwin (macOS). Darwin ABI differs from AIX and ELF.
9+
; To add support for AIX, *BSD or *Linux, please make separate implementations.
10+
111
#define TOKEN_PASTE(x,y) x##y
212
#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
313

14+
.machine ppc7400 ; = G4, Rosetta
415
.text
5-
.align 2
616

717
.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
18+
.align 2
19+
820
PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
9-
# Make space on the stack for caller registers
10-
addi r1,r1,-80
21+
; Make space on the stack for caller registers
22+
; (Should we rather use red zone? See libphobos example.)
23+
subi r1,r1,80
24+
25+
; Get LR
26+
mflr r0
1127

12-
# Save caller registers
13-
stw r13,0(r1)
14-
stw r14,4(r1)
15-
stw r15,8(r1)
16-
stw r16,12(r1)
17-
stw r17,16(r1)
18-
stw r18,20(r1)
19-
stw r19,24(r1)
20-
stw r20,28(r1)
21-
stw r21,32(r1)
28+
; Save caller registers
29+
stw r31,0(r1)
30+
stw r30,4(r1)
31+
stw r29,8(r1)
32+
stw r28,12(r1)
33+
stw r27,16(r1)
34+
stw r26,20(r1)
35+
stw r25,24(r1)
36+
stw r24,28(r1)
37+
stw r23,32(r1)
2238
stw r22,36(r1)
23-
stw r23,40(r1)
24-
stw r24,44(r1)
25-
stw r25,48(r1)
26-
stw r26,52(r1)
27-
stw r27,56(r1)
28-
stw r28,60(r1)
29-
stw r29,64(r1)
30-
stw r30,68(r1)
31-
stw r31,72(r1)
39+
stw r21,40(r1)
40+
stw r20,44(r1)
41+
stw r19,48(r1)
42+
stw r18,52(r1)
43+
stw r17,56(r1)
44+
stw r16,60(r1)
45+
stw r15,64(r1)
46+
stw r14,68(r1)
47+
stw r13,72(r1)
3248

33-
# Save return address
34-
mflr r0
49+
; Save return address
50+
; Possibly should rather be saved into linkage area, see libphobos and IBM docs
3551
stw r0,76(r1)
3652

37-
# Save stack pointer to first argument
53+
; Save stack pointer to first argument
3854
stw r1,0(r3)
3955

40-
# Load stack pointer from second argument
56+
; Load stack pointer from second argument
4157
lwz r1,0(r4)
4258

43-
# Restore caller registers
44-
lwz r13,0(r1)
45-
lwz r14,4(r1)
46-
lwz r15,8(r1)
47-
lwz r16,12(r1)
48-
lwz r17,16(r1)
49-
lwz r18,20(r1)
50-
lwz r19,24(r1)
51-
lwz r20,28(r1)
52-
lwz r21,32(r1)
59+
; Load return address
60+
lwz r0,76(r1)
61+
62+
; Restore caller registers
63+
lwz r13,72(r1)
64+
lwz r14,68(r1)
65+
lwz r15,64(r1)
66+
lwz r16,60(r1)
67+
lwz r17,56(r1)
68+
lwz r18,52(r1)
69+
lwz r19,48(r1)
70+
lwz r20,44(r1)
71+
lwz r21,40(r1)
5372
lwz r22,36(r1)
54-
lwz r23,40(r1)
55-
lwz r24,44(r1)
56-
lwz r25,48(r1)
57-
lwz r26,52(r1)
58-
lwz r27,56(r1)
59-
lwz r28,60(r1)
60-
lwz r29,64(r1)
61-
lwz r30,68(r1)
62-
lwz r31,72(r1)
73+
lwz r23,32(r1)
74+
lwz r24,28(r1)
75+
lwz r25,24(r1)
76+
lwz r26,20(r1)
77+
lwz r27,16(r1)
78+
lwz r28,12(r1)
79+
lwz r29,8(r1)
80+
lwz r30,4(r1)
81+
lwz r31,0(r1)
6382

64-
# Load return address
65-
lwz r0,76(r1)
83+
; Set LR
6684
mtlr r0
6785

68-
# Pop stack frame
86+
; Pop stack frame
6987
addi r1,r1,80
7088

71-
# Jump to return address
89+
; Jump to return address
7290
blr
73-

coroutine/ppc/Context.h

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <string.h>
1010

1111
#define COROUTINE __attribute__((noreturn)) void
12+
#define COROUTINE_LIMITED_ADDRESS_SPACE
1213

1314
enum {
1415
COROUTINE_REGISTERS =

coroutine/ppc64/Context.S

+70-51
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,89 @@
1+
; Based on the code by Samuel Williams. Created by Sergey Fedorov on 04/06/2022.
2+
; Credits to Samuel Williams, Rei Odaira and Iain Sandoe. Errors, if any, are mine.
3+
; Some relevant examples: https://github.com/gcc-mirror/gcc/blob/master/libphobos/libdruntime/config/powerpc/switchcontext.S
4+
; https://github.com/gcc-mirror/gcc/blob/master/libgcc/config/rs6000/darwin-gpsave.S
5+
; https://www.ibm.com/docs/en/aix/7.2?topic=epilogs-saving-gprs-only
6+
7+
; Notice that this code is only for Darwin (macOS). Darwin ABI differs from AIX and ELF.
8+
; To add support for AIX, *BSD or *Linux, please make separate implementations.
9+
110
#define TOKEN_PASTE(x,y) x##y
211
#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name)
312

13+
.machine ppc64 ; = G5
414
.text
5-
.align 3
615

716
.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
8-
PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
9-
# Make space on the stack for caller registers
10-
addi r1,r1,-152
17+
.align 2
1118

12-
# Save caller registers
13-
std r14,0(r1)
14-
std r15,8(r1)
15-
std r16,16(r1)
16-
std r17,24(r1)
17-
std r18,32(r1)
18-
std r19,40(r1)
19-
std r20,48(r1)
20-
std r21,56(r1)
21-
std r22,64(r1)
22-
std r23,72(r1)
23-
std r24,80(r1)
24-
std r25,88(r1)
25-
std r26,96(r1)
26-
std r27,104(r1)
27-
std r28,112(r1)
28-
std r29,120(r1)
29-
std r30,128(r1)
30-
std r31,136(r1)
19+
PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
20+
; Make space on the stack for caller registers
21+
; (Should we rather use red zone? See libphobos example.)
22+
subi r1,r1,160
3123

32-
# Save return address
24+
; Get LR
3325
mflr r0
34-
std r0,144(r1)
3526

36-
# Save stack pointer to first argument
27+
; Save caller registers
28+
std r31,0(r1)
29+
std r30,8(r1)
30+
std r29,16(r1)
31+
std r28,24(r1)
32+
std r27,32(r1)
33+
std r26,40(r1)
34+
std r25,48(r1)
35+
std r24,56(r1)
36+
std r23,64(r1)
37+
std r22,72(r1)
38+
std r21,80(r1)
39+
std r20,88(r1)
40+
std r19,96(r1)
41+
std r18,104(r1)
42+
std r17,112(r1)
43+
std r16,120(r1)
44+
std r15,128(r1)
45+
std r14,136(r1)
46+
std r13,144(r1)
47+
48+
; Save return address
49+
; Possibly should rather be saved into linkage area, see libphobos and IBM docs
50+
std r0,152(r1)
51+
52+
; Save stack pointer to first argument
3753
std r1,0(r3)
3854

39-
# Load stack pointer from second argument
55+
; Load stack pointer from second argument
4056
ld r1,0(r4)
4157

42-
# Restore caller registers
43-
ld r14,0(r1)
44-
ld r15,8(r1)
45-
ld r16,16(r1)
46-
ld r17,24(r1)
47-
ld r18,32(r1)
48-
ld r19,40(r1)
49-
ld r20,48(r1)
50-
ld r21,56(r1)
51-
ld r22,64(r1)
52-
ld r23,72(r1)
53-
ld r24,80(r1)
54-
ld r25,88(r1)
55-
ld r26,96(r1)
56-
ld r27,104(r1)
57-
ld r28,112(r1)
58-
ld r29,120(r1)
59-
ld r30,128(r1)
60-
ld r31,136(r1)
58+
; Load return address
59+
ld r0,152(r1)
60+
61+
; Restore caller registers
62+
ld r13,144(r1)
63+
ld r14,136(r1)
64+
ld r15,128(r1)
65+
ld r16,120(r1)
66+
ld r17,112(r1)
67+
ld r18,104(r1)
68+
ld r19,96(r1)
69+
ld r20,88(r1)
70+
ld r21,80(r1)
71+
ld r22,72(r1)
72+
ld r23,64(r1)
73+
ld r24,56(r1)
74+
ld r25,48(r1)
75+
ld r26,40(r1)
76+
ld r27,32(r1)
77+
ld r28,24(r1)
78+
ld r29,16(r1)
79+
ld r30,8(r1)
80+
ld r31,0(r1)
6181

62-
# Load return address
63-
ld r0,144(r1)
82+
; Set LR
6483
mtlr r0
6584

66-
# Pop stack frame
67-
addi r1,r1,152
85+
; Pop stack frame
86+
addi r1,r1,160
6887

69-
# Jump to return address
88+
; Jump to return address
7089
blr

coroutine/ppc64/Context.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
enum {
1414
COROUTINE_REGISTERS =
15-
19 /* 18 general purpose registers (r14–r31) and 1 return address */
15+
20 /* 19 general purpose registers (r13–r31) and 1 return address */
1616
+ 4 /* space for fiber_entry() to store the link register */
1717
};
1818

@@ -44,7 +44,7 @@ static inline void coroutine_initialize(
4444
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);
4545

4646
/* Skip a global prologue that sets the TOC register */
47-
context->stack_pointer[18] = ((char*)start) + 8;
47+
context->stack_pointer[19] = ((char*)start) + 8;
4848
}
4949

5050
struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);

dln.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ static void dln_loaderror(const char *format, ...);
4141
# include <strings.h>
4242
#endif
4343

44+
#if defined __APPLE__
45+
# include <AvailabilityMacros.h>
46+
#endif
47+
4448
#ifndef xmalloc
4549
void *xmalloc();
4650
void *xcalloc();
@@ -58,7 +62,7 @@ void *xrealloc();
5862
#include <sys/stat.h>
5963

6064
#ifndef S_ISDIR
61-
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
65+
# define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
6266
#endif
6367

6468
#ifdef HAVE_SYS_PARAM_H

error.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -668,7 +668,7 @@ bug_important_message(FILE *out, const char *const msg, size_t len)
668668

669669
#undef CRASH_REPORTER_MAY_BE_CREATED
670670
#if defined(__APPLE__) && \
671-
(!defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6)
671+
(!defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 || defined(__POWERPC__)) /* 10.6 PPC case */
672672
# define CRASH_REPORTER_MAY_BE_CREATED
673673
#endif
674674
static void

0 commit comments

Comments
 (0)