Skip to content

Commit a6a6a20

Browse files
committed
Fix linker errors with latest Swift toolchain snapshot
The main-snapshot-2026-01-09 toolchain changed swift_allocObject to call posix_memalign instead of malloc, and pulls in additional newlib symbols. The previous Swift posix_memalign stub was being dead-stripped by the whole-module optimizer since nothing in Swift code references it directly. - Move posix_memalign to C in setup.c where it won't be dead-stripped - Add bare-metal stubs for newlib syscalls (_getentropy/getentropy, _kill, _getpid, _close, _lseek, _read, _write, _fstat, _isatty) - Add -DTARGET_PLAYDATE=1 to device toolset to match the SDK's own build system (common.mk), enabling the correct #if TARGET_PLAYDATE branch - Make pdrealloc non-static so Xkpd CLodePNG can reference it - Update .swift-version to main-snapshot-2026-01-09
1 parent edb42dd commit a6a6a20

File tree

8 files changed

+98
-25
lines changed

8 files changed

+98
-25
lines changed

.swift-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
main-snapshot-2025-05-25
1+
main-snapshot-2026-01-09

Examples/FlappySwift/Package.resolved

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Examples/Pong/Package.resolved

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Examples/Xkpd/Package.resolved

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
#ifdef TARGET_PLAYDATE
2-
extern void* pdrealloc(void* ptr, size_t size);
3-
void* lodepng_malloc(size_t size) { return pdrealloc(NULL, size); }
4-
void* lodepng_realloc(void* ptr, size_t size) { return pdrealloc(ptr, size); }
5-
void lodepng_free(void* ptr) { if(ptr) pdrealloc(ptr, 0); }
2+
#include <stddef.h>
3+
extern void* malloc(size_t);
4+
extern void* realloc(void*, size_t);
5+
extern void free(void*);
66
#else
77
#include <stdlib.h>
8-
void* lodepng_malloc(size_t size) { return malloc(size); }
9-
void* lodepng_realloc(void* ptr, size_t size) { return realloc(ptr, size); }
10-
void lodepng_free(void* ptr) { free(ptr); }
118
#endif
129

10+
void* lodepng_malloc(size_t size) { return malloc(size); }
11+
void* lodepng_realloc(void* ptr, size_t size) { return realloc(ptr, size); }
12+
void lodepng_free(void* ptr) { free(ptr); }
13+

Sources/CPlaydate/setup.c

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ typedef int (PDEventHandler)(PlaydateAPI* playdate, PDSystemEvent event, uint32_
55

66
extern PDEventHandler eventHandler;
77

8-
static void* (*pdrealloc)(void* ptr, size_t size);
8+
void* (*pdrealloc)(void* ptr, size_t size);
99

1010
int eventHandlerShim(PlaydateAPI* playdate, PDSystemEvent event, uint32_t arg)
1111
{
@@ -21,6 +21,46 @@ void* _malloc_r(struct _reent* _REENT, size_t nbytes) { return pdrealloc(NULL,nb
2121
void* _realloc_r(struct _reent* _REENT, void* ptr, size_t nbytes) { return pdrealloc(ptr,nbytes); }
2222
void _free_r(struct _reent* _REENT, void* ptr ) { if ( ptr != NULL ) pdrealloc(ptr,0); }
2323

24+
int getentropy(void *buffer, size_t length) {
25+
return -1;
26+
}
27+
28+
int _getentropy(void *buffer, size_t length) {
29+
return -1;
30+
}
31+
32+
int _kill(int pid, int sig) {
33+
return -1;
34+
}
35+
36+
int _getpid(void) {
37+
return 1;
38+
}
39+
40+
int _close(int fd) {
41+
return -1;
42+
}
43+
44+
int _lseek(int fd, int offset, int whence) {
45+
return -1;
46+
}
47+
48+
int _read(int fd, void *buf, int count) {
49+
return -1;
50+
}
51+
52+
int _write(int fd, const void *buf, int count) {
53+
return -1;
54+
}
55+
56+
int _fstat(int fd, void *buf) {
57+
return -1;
58+
}
59+
60+
int _isatty(int fd) {
61+
return 0;
62+
}
63+
2464
#else
2565

2666
void* malloc(size_t nbytes) { return pdrealloc(NULL,nbytes); }
@@ -29,4 +69,11 @@ void free(void* ptr ) { if ( ptr != NULL ) pdrealloc(ptr,0); }
2969

3070
#endif
3171

72+
int posix_memalign(void **memptr, size_t alignment, size_t size) {
73+
void *ptr = pdrealloc(NULL, size);
74+
if (!ptr) return 12; // ENOMEM
75+
*memptr = ptr;
76+
return 0;
77+
}
78+
3279
void *swift_coroFrameAlloc(size_t bytes, unsigned long long typeId) { return pdrealloc(NULL,bytes); }

Sources/PlaydateKit/Playdate.swift

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,6 @@ public enum Playdate {
4141
private nonisolated(unsafe) static var _playdateAPI: PlaydateAPI?
4242
}
4343

44-
/// Implement `posix_memalign(3)`, which is required by the Embedded Swift runtime but is
45-
/// not provided by the Playdate C library.
46-
@_documentation(visibility: internal)
47-
@_cdecl("posix_memalign") public func posix_memalign(
48-
_ memptr: UnsafeMutablePointer<UnsafeMutableRawPointer?>,
49-
_ alignment: Int,
50-
_ size: Int
51-
) -> CInt {
52-
guard let allocation = malloc(Int(size + alignment - 1)) else { fatalError() }
53-
let misalignment = Int(bitPattern: allocation) % alignment
54-
precondition(misalignment == 0)
55-
memptr.pointee = allocation
56-
return 0
57-
}
58-
5944
/// Implement `arc4random_buf` which is required by the Embedded Swift runtime for Hashable, Set, Dictionary,
6045
/// and random-number generating APIs but is not provided by the Playdate C library.
6146
@_documentation(visibility: internal)

Toolsets/toolset_device.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"-mfloat-abi=hard",
1616
"-mfpu=fpv5-sp-d16",
1717
"-D__FPU_USED=1",
18+
"-DTARGET_PLAYDATE=1",
1819

1920
"-falign-functions=16",
2021
"-fshort-enums"

0 commit comments

Comments
 (0)