macOS universal binary, take 2

- Add new target `macos-lipo`.
   - Created by compiling a universal x86 binary (no PGO) and a standard Apple silicon binary (with PGO), then combining them into a Mach-O fat binary
   - To keep only one copy of the net, we add custom loading logic in the x86 section. The executable reads its own path and mmaps the net that's in the ARM section.
       - The offset and size (from the executable base) of the mapping is injected after compilation in `patch_x86_slice.sh`
   - avx512 on macOS isn't advertised in the xcr0 register by default. The simple solution I came up with is to execute a dummy AVX512 instruction, which sets up the register, before calling `__builtin_cpu_init`.

Some housekeeping as well:
- Rename `armv8-universal` -> `arm64-universal`.
- Add standard copyright headers to the files we've added recently.

Potential follow-ups:
- Disservin's Makefile cleanup
- Alternative ideas for the net loading. In particular, this will error out if the user strips the binary (since that'll invalidate the offset).

closes https://github.com/official-stockfish/Stockfish/pull/6860

No functional change

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
anematode
2026-05-29 19:05:53 +02:00
committed by Joost VandeVondele
co-authored by Copilot Autofix powered by AI
parent 24a551899e
commit 8cbca11a53
14 changed files with 441 additions and 198 deletions
+11 -16
View File
@@ -46,23 +46,13 @@
// Note that this does not work in Microsoft Visual Studio.
#if !defined(UNIVERSAL_BINARY) && !defined(_MSC_VER) && !defined(NNUE_EMBEDDING_OFF)
INCBIN(EmbeddedNNUE, EvalFileDefaultName);
#elif defined(UNIVERSAL_BINARY_MACOS_X86_SLICE)
// Determined at runtime, see universal/nnue_embed.cpp
extern const unsigned char* const gEmbeddedNNUEData;
extern const unsigned int gEmbeddedNNUESize;
#elif defined(UNIVERSAL_BINARY)
// When building for the universal binary, use C++26 #embed with weak symbols so that a
// separate, non-LTO nnue_embed.o (with strong symbols) can override them during the LTO link,
// (INCBIN can't deduplicate.)
#define WEAK_SYM __attribute__((weak))
extern const unsigned char gEmbeddedNNUEData[] WEAK_SYM =
#ifdef __has_embed
{
#embed EvalFileDefaultName
};
const int padding = 0;
#else
#include "../universal/network_dump.inc"
;
const int padding = 1; // trailing NUL byte
#endif
extern const unsigned int gEmbeddedNNUESize WEAK_SYM = sizeof(gEmbeddedNNUEData) - padding;
extern const unsigned char gEmbeddedNNUEData[];
extern const unsigned int gEmbeddedNNUESize;
#else
const unsigned char gEmbeddedNNUEData[1] = {0x0};
const unsigned int gEmbeddedNNUESize = 1;
@@ -257,6 +247,11 @@ void Network::load_internal() {
}
};
#ifdef UNIVERSAL_BINARY_MACOS_X86_SLICE
if (gEmbeddedNNUEData == nullptr) // failed embedded load
return;
#endif
MemoryBuffer buffer(const_cast<char*>(reinterpret_cast<const char*>(gEmbeddedNNUEData)),
size_t(gEmbeddedNNUESize));