セキュリティキャンプ2024のCコンパイラゼミの記録。顔合わせ回を除いて公開しました。
事前学習期間
実装した機能
- 文字列リテラルのエスケープ
- 文字リテラル
- 代入演算子を演算子として使えるようにした
- インクリメント・デクリメント
__LINE__
・__FILE__
- ループ内のbreakとcontinue
- switch文とcase・default
- voidポインタ
&&
と||
の短絡評価- 空のreturn文
- 比較演算子
- 複合代入演算子
- 単項not演算子
- long型
- 各ファイルのセルフホスト対応
- 構造体のアライメント
- 構造体のオフセットを取得するコンパイラマジック
- ポインタ同士の減算
- グローバル変数の初期化式
- 16バイトアライメントの実装 (大会期間中に再実装した)
主なバグ修正
- インクリメントの実装でノードをコピーする実装にしていた。そのノードに対して2回意味解析が走っていたが、2回目の意味解析は想定しておらず、その結果セグメンテーション違反が発生したのを修正した。
- 配列のインデックスアクセスの実装にバグがあり、mov命令の箇所でセグメンテーション違反が発生したのを修正した。
- アセンブリを出力する際に関数をグローバルに公開するフラグをセットしていなかったのを修正した。
- 2世代目コンパイラを動かす際に、何らかの理由でファイルを読み込む関数が動作せず、空のアセンブリが生成されてしまった。代わりに簡易的なファイルを読み込む関数に置き換えた。
- インクリメントの際に32ビットレジスタを使用していて、ポインタのインクリメントをすると上位32ビットが切り捨てられてしまった。その結果異なるファイルでmemcmpする際にセグメンテーション違反が発生したのを修正した。
- グローバル変数の初期化式を実装していないことに気づかず、ファイルを読み込む関数に誤った引数を渡していたのを修正した。
セキュキャン本番
実装した機能
- 16バイトアライメントの再実装
- セルフホストの実現
- 整数拡張・算術型変換
#include
の実装
主なバグ修正
16バイトアライメントの実装ミスにより、callocが正常に動かないバグが発生した。
- スタックにローカル変数を積んでいる箇所が16バイトアライメントに対応していなかったのを修正した。
- スタックのオフセットを計算する箇所で誤った式を指定していたのを修正した。
- 1回目の16バイトアライメントの実装方法では条件分岐やループに対応できないことがわかり、静的な実装から動的な実装に置き換えた。
適切な算術型変換・整数拡張が行われておらず、様々なバグが発生した。
- 負数の割り算を行う際に適切に算術型変換が行われていなかったのを修正。例えば-200が約42億と扱われてしまっていた。
- 整数を拡張する際には符号を考慮した拡張をしないといけないが、0で埋める整数拡張の命令を使用してしまっていたのを修正した。
- 比較で適切に算術型変換が行われず、負数 > 正数になってしまったのを修正した。