]> git.sesse.net Git - stockfish/blobdiff - src/syzygy/tbprobe.cpp
Do not use GCC extension for anonymous unions
[stockfish] / src / syzygy / tbprobe.cpp
index 46c513d256097f23c8044c09e86c3cceacefabea..b553ac9fd4946a3b620aee9557deced93bf4a3c7 100644 (file)
@@ -125,18 +125,39 @@ struct PairsData {
     int groupLen[TBPIECES+1];      // Number of pieces in a given group: KRKN -> (3, 1)
 };
 
-// Helper struct to avoid to manually define entry copy c'tor as we should
-// because default one is not compatible with std::atomic_bool.
+// Helper struct to avoid manually defining entry copy constructor as we
+// should because the default one is not compatible with std::atomic_bool.
 struct Atomic {
     Atomic() = default;
     Atomic(const Atomic& e) { ready = e.ready.load(); } // MSVC 2013 wants assignment within body
     std::atomic_bool ready;
 };
 
-struct WDLEntry : public Atomic {
-    WDLEntry(const std::string& code);
-   ~WDLEntry();
+// We define types for the different parts of the WLDEntry and DTZEntry with
+// corresponding specializations for pieces or pawns.
+
+struct WLDEntryPiece {
+    PairsData* precomp;
+};
 
+struct WDLEntryPawn {
+    uint8_t pawnCount[2];     // [Lead color / other color]
+    WLDEntryPiece file[2][4]; // [wtm / btm][FILE_A..FILE_D]
+};
+
+struct DTZEntryPiece {
+    PairsData* precomp;
+    uint16_t map_idx[4]; // WDLWin, WDLLoss, WDLCursedWin, WDLCursedLoss
+    uint8_t* map;
+};
+
+struct DTZEntryPawn {
+    uint8_t pawnCount[2];
+    DTZEntryPiece file[4];
+    uint8_t* map;
+};
+
+struct TBEntry : public Atomic {
     void* baseAddress;
     uint64_t mapping;
     Key key;
@@ -144,46 +165,24 @@ struct WDLEntry : public Atomic {
     int pieceCount;
     bool hasPawns;
     bool hasUniquePieces;
+};
+
+// Now the main types: WDLEntry and DTZEntry
+struct WDLEntry : public TBEntry {
+    WDLEntry(const std::string& code);
+   ~WDLEntry();
     union {
-        struct {
-            PairsData* precomp;
-        } pieceTable[2]; // [wtm / btm]
-
-        struct {
-            uint8_t pawnCount[2]; // [Lead color / other color]
-            struct {
-                PairsData* precomp;
-            } file[2][4]; // [wtm / btm][FILE_A..FILE_D]
-        } pawnTable;
+        WLDEntryPiece pieceTable[2]; // [wtm / btm]
+        WDLEntryPawn  pawnTable;
     };
 };
 
-struct DTZEntry : public Atomic {
+struct DTZEntry : public TBEntry {
     DTZEntry(const WDLEntry& wdl);
    ~DTZEntry();
-
-    void* baseAddress;
-    uint64_t mapping;
-    Key key;
-    Key key2;
-    int pieceCount;
-    bool hasPawns;
-    bool hasUniquePieces;
     union {
-        struct {
-            PairsData* precomp;
-            uint16_t map_idx[4]; // WDLWin, WDLLoss, WDLCursedWin, WDLCursedLoss
-            uint8_t* map;
-        } pieceTable;
-
-        struct {
-            uint8_t pawnCount[2];
-            struct {
-                PairsData* precomp;
-                uint16_t map_idx[4];
-            } file[4];
-            uint8_t* map;
-        } pawnTable;
+        DTZEntryPiece pieceTable;
+        DTZEntryPawn  pawnTable;
     };
 };
 
@@ -239,7 +238,13 @@ template<typename T, int LE> T number(void* addr)
     const union { uint32_t i; char c[4]; } Le = { 0x01020304 };
     const bool IsLittleEndian = (Le.c[0] == 4);
 
-    T v = *((T*)addr);
+    T v;
+
+    if ((uintptr_t)addr & (alignof(T) - 1)) // Unaligned pointer (very rare)
+        std::memcpy(&v, addr, sizeof(T));
+    else
+        v = *((T*)addr);
+
     if (LE != IsLittleEndian)
         swap_byte(v);
     return v;
@@ -1061,10 +1066,10 @@ void do_init(Entry& e, T& p, uint8_t* data) {
 
     enum { Split = 1, HasPawns = 2 };
 
-    uint8_t flags = *data++;
+    assert(e.hasPawns        == !!(*data & HasPawns));
+    assert((e.key != e.key2) == !!(*data & Split));
 
-    assert(e.hasPawns        == !!(flags & HasPawns));
-    assert((e.key != e.key2) == !!(flags & Split));
+    data++; // First byte stores flags
 
     const int Sides = IsWDL && (e.key != e.key2) ? 2 : 1;
     const File MaxFile = e.hasPawns ? FILE_D : FILE_A;
@@ -1201,7 +1206,7 @@ WDLScore search(Position& pos, ProbeState* result) {
 
         moveCount++;
 
-        pos.do_move(move, st, pos.gives_check(move));
+        pos.do_move(move, st);
         value = -search(pos, result);
         pos.undo_move(move);
 
@@ -1449,7 +1454,7 @@ int Tablebases::probe_dtz(Position& pos, ProbeState* result) {
     {
         bool zeroing = pos.capture(move) || type_of(pos.moved_piece(move)) == PAWN;
 
-        pos.do_move(move, st, pos.gives_check(move));
+        pos.do_move(move, st);
 
         // For zeroing moves we want the dtz of the move _before_ doing it,
         // otherwise we will get the dtz of the next move sequence. Search the
@@ -1523,7 +1528,7 @@ bool Tablebases::root_probe(Position& pos, Search::RootMoves& rootMoves, Value&
     // Probe each move
     for (size_t i = 0; i < rootMoves.size(); ++i) {
         Move move = rootMoves[i].pv[0];
-        pos.do_move(move, st, pos.gives_check(move));
+        pos.do_move(move, st);
         int v = 0;
 
         if (pos.checkers() && dtz > 0) {
@@ -1659,7 +1664,7 @@ bool Tablebases::root_probe_wdl(Position& pos, Search::RootMoves& rootMoves, Val
     // Probe each move
     for (size_t i = 0; i < rootMoves.size(); ++i) {
         Move move = rootMoves[i].pv[0];
-        pos.do_move(move, st, pos.gives_check(move));
+        pos.do_move(move, st);
         WDLScore v = -Tablebases::probe_wdl(pos, &result);
         pos.undo_move(move);