私は歴史的な関数型言語インタープリター (EMAS の KRC) を最新のシステム (Unix の C) に移植しようとしていますが、再配置する必要があるポインターを知るために、ヒープへのポインターのスタックをスキャンできることを期待するガベージ コレクターがあります。 GC 中にヒープ内のオブジェクトが移動されたとき。これが機能するには、ヒープを指すすべての関数引数とローカル変数がスタック内にある必要があります。
現在、「レジスタ」キーワードが「必要に応じてこの変数をレジスタに入れることができる」ことを意味し、それ以外の場合はスタック上にあった時代がありましたが、最近ではすべての (GCC、Clang、Tinyc/tcc) C コンパイラはこの動作を無効にする方法がないため、ローカル変数をレジスタに入れます。その結果、GC は進行中の関数に属するいくつかの値を失い、それらを保持できず、ヒープが破損します。
これらのコンパイラのいずれかに元の C セマンティクスを使用するように指示する方法はありますか?「登録」と言わない限り、すべてのローカル変数はスタック上にありますか?
私はいくつかの疣贅の「解決策」を持っています:
- 各ヒープ指向のローカル変数のアドレスを取得するための余分なコードをあらゆる場所に追加し、それをダミー関数に渡します。
- 関数のインライン化とその結果としてのインライン化された関数のパラメータの最適化を回避するために、すべての静的関数をグローバルにします。
- すべてのマシン レジスタをスタックにプッシュするスタブで GC() 関数を囲み、実際の GC() 関数を呼び出してからそれらをポップします。
これらはすべて問題を改善しているように見えますが、非常にハックで信頼性が低くなります。
すべての関数パラメーターとローカル変数がスタック上にあることを確認するために、必要な結果を達成するためのより良い方法はありますか?