user32818: I am building a chess engine and I want the engine to directly generate legal moves (instead of pseudo legal + validation).
For this, I am keeping in the chess board structure a bitboard of all attacked squares, all checker squares, all pinned squares by the player who last made the move. Sort of like this'
struct ChessBoard {
    Bitboard attacked, checkers, pinned;
    ...
};

Now I plan for the architecture for this engine to be relatively simple, a function which fill a moves list with legal moves for a chess board, a move maker function, and a search function (well, it's more complex than that). Like the following
void legal_moves(ChessBoard* board, MoveList* list);
void make_move(ChessBoard* board, Move move);
Move search(ChessBoard* board);

// search will call legal_moves() and make_move()

Now the question is, should legal_moves() update the attacked, checkers, pinned members or should make_move()? It should be more performant to let legal_moves() handle that since it gets the attacks for any piece any way, but my problem with this is that the search function  may call legal_moves() but then not call make_move() for each move?
Writing this I am leaning towards legal_moves() but it's kinda complex and I would appreciate input on this.

user27860: My current engine uses pseudo-legal move generation, but one of the previous versions used fully legal move generation as yours will.
My advice is to update the information in make_move. make_move is concerned with making a move on the board, and as soon as a move is made, what pieces are pinned, attacked, or checked immediately changes, so you need to bring that information up to date.
legal_moves on the other hand should be concerned with move generation. It would have no way of knowing what moves it generates would eventually be played, so it wouldn't be able to do any updating of checkers, pinned, or attacked.
In pseduo-code:
void make_move(ChessBoard* board, Move move) {
    // update the relavant internal board state
    ...
    board->pinned = pinned_pieces(board);
    board->checkers = checking_pieces(board);
    board->attacked = attacked_squares(board);
}

Notice how updating pinned, checkers, and attacked only really makes sense in make_move, since that's only when the internal state of the board has changed, and when you would need to re-compute the information.

32818: <p>I am building a chess engine and I want the engine to directly generate legal moves (instead of pseudo legal + validation).</p>
<p>For this, I am keeping in the chess board structure a bitboard of all attacked squares, all checker squares, all pinned squares by the player who last made the move. Sort of like this'</p>
<pre><code>struct ChessBoard {
    Bitboard attacked, checkers, pinned;
    ...
};
</code></pre>
<p>Now I plan for the architecture for this engine to be relatively simple, a function which fill a moves list with legal moves for a chess board, a move maker function, and a search function (well, it's more complex than that). Like the following</p>
<pre><code>void legal_moves(ChessBoard* board, MoveList* list);
void make_move(ChessBoard* board, Move move);
Move search(ChessBoard* board);

// search will call legal_moves() and make_move()
</code></pre>
<p>Now the question is, should <code>legal_moves()</code> update the <code>attacked, checkers, pinned</code> members or should <code>make_move()</code>? It should be more performant to let <code>legal_moves()</code> handle that since it gets the attacks for any piece any way, but my problem with this is that the search function  may call <code>legal_moves()</code> but then not call <code>make_move()</code> for each move?</p>
<p>Writing this I am leaning towards <code>legal_moves()</code> but it's kinda complex and I would appreciate input on this.</p>
 27860: <p>My current engine uses pseudo-legal move generation, but one of the previous versions used fully legal move generation as yours will.</p>
<p>My advice is to update the information in <code>make_move</code>. <code>make_move</code> is concerned with making a move on the board, and as soon as a move is made, what pieces are pinned, attacked, or checked immediately changes, so you need to bring that information up to date.</p>
<p><code>legal_moves</code> on the other hand should be concerned with move generation. It would have no way of knowing what moves it generates would eventually be played, so it wouldn't be able to do any updating of <code>checkers</code>, <code>pinned</code>, or <code>attacked</code>.</p>
<p>In pseduo-code:</p>
<pre><code>void make_move(ChessBoard* board, Move move) {
    // update the relavant internal board state
    ...
    board-&gt;pinned = pinned_pieces(board);
    board-&gt;checkers = checking_pieces(board);
    board-&gt;attacked = attacked_squares(board);
}
</code></pre>
<p>Notice how updating <code>pinned</code>, <code>checkers</code>, and <code>attacked</code> only really makes sense in <code>make_move</code>, since that's only when the internal state of the board has changed, and when you would need to re-compute the information.</p>
