https://github.com/Latte72R/LaCC
Latte's C Compiler
https://github.com/Latte72R/LaCC
c compiler
Last synced: about 13 hours ago
JSON representation
Latte's C Compiler
- Host: GitHub
- URL: https://github.com/Latte72R/LaCC
- Owner: Latte72R
- License: mit
- Created: 2024-09-26T19:59:05.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2026-06-05T23:44:10.000Z (21 days ago)
- Last Synced: 2026-06-06T00:12:35.428Z (21 days ago)
- Topics: c, compiler
- Language: C
- Homepage:
- Size: 1.91 MB
- Stars: 24
- Watchers: 1
- Forks: 1
- Open Issues: 9
-
Metadata Files:
- Readme: README-ja.md
- License: LICENSE
Awesome Lists containing this project
README
[English](README.md) | 日本語

LaCC は, C コンパイラの仕様やメモリ構造の理解を目的に開発された, 必要最小限の機能だけを備えたシンプルな C コンパイラです.
[](https://deepwiki.com/Latte72R/LaCC) [](https://github.com/Latte72R/LaCC/blob/main/LICENSE)
## サポートされている機能
### 1. データ型
- **プリミティブ型**: `int`, `char`, `void`, `unsigned`, `long`, `long long`, `short`, `_Bool`
- **派生型**: ポインタ (`T*`), 配列 (`T[]`)
- **複合型**: 構造体 (`struct`), 共用体 (`union`), 列挙体 (`enum`)
#### float/double の扱い
ヘッダ互換性のために `float` と `double` を「擬似的に」サポートしています.
- トークナイズとパースはできますが, 数値演算や比較, コード生成は未実装です.
- `sizeof(float)` は 4, `sizeof(double)` は 8 として扱います(LP64 前提).
`long double` も簡易的に 8 バイトとして扱います.
- `typedef float _Float32;` や `typedef double _Float64;` といったヘッダ内の型定義は通りますが, これらの型での演算は未サポートです.
(将来的に `TY_FLOAT`/`TY_DOUBLE` の導入と算術・ABI 対応を段階的に実装する予定です.)
### 2. 関数
- **定義:**
パラメータと戻り値の型を指定できます.
- **宣言と呼び出し:**
関数の定義, 呼び出し, `return` での値を返却が可能です.
### 3. グローバル&ローカル変数
グローバル変数とローカル(スタック上)変数の宣言がサポートされています.
### 4. 制御構造
- **条件分岐**
- `if (condition) { … }`
- `else { … }`
- **ループ**
- `do { … } while (condition);`
- **ループ制御**
- `continue`
### 5. 演算子
- **算術**: `+`, `-`, `*`, `/`, `%`
- **比較**: `==`, `!=`, `<`, `<=`, `>`, `>=`
- **論理**: `&&`, `||`, `!`
- **ビット演算**: `&`, `|`, `^`, `~`, `<<`, `>>`
### 6. その他
- **インクルード指令**
ダブルクォート形式の `#include "foo.h"` と山括弧形式の `#include ` を処理できます.
ダブルクォートはインクルード元のファイルと同じディレクトリを優先し, 山括弧は登録済みのインクルードパスを探索します.
- **プリプロセッサマクロ**
オブジェクト形式および関数形式の `#define`(文字列化 `#`・トークン連結 `##` を含む)をトークナイズ時に展開します.
マクロ展開中に発生したエラーや警告も, 展開元ファイル・元行へ遡って報告されるため複雑なヘッダでも位置がずれません.
- **条件付きコンパイルディレクティブ**
- **組み込み済みマクロ**
`__LACC__`, `__x86_64__`, `__LP64__` に加え, 各種互換マクロを定義し, Unix 系ヘッダが環境を判別しやすいようにしています.
- **配列・構造体・共用体の初期化リスト**
```c
int values[3] = {a, b, c};
int matrix[2][3] = {{a, b}, {c, d}};
struct A value = {{b, c, d}, e, f};
struct Pair pair = {.left = a, .right = b};
char str[15] = "Hello, World!\n";
```
ローカル変数では実行時式を含む配列初期化, 多次元配列初期化,
位置指定および指示付きの構造体・共用体初期化に対応しています.
構造体内の配列やネストした構造体にも実行時式を使用できます.
グローバル変数と `static` 変数の初期化には, コンパイル時定数または
対応している文字列リテラルが必要です.
- **extern 宣言**
基本型, ポインタ, 配列などの外部変数宣言が可能です.
- **typedef サポート**
型エイリアスを作る `typedef` が使えます.
- **型修飾子およびストレージクラス指定子:**
`const`, `volatile`, `static`, `signed`, `unsigned` に加え, システムヘッダで頻出するポインタ専用修飾子(`restrict`, `_Nullable`, `_Nonnull`, `__strong`, `__weak` など)もパースだけ対応しています.
- **`goto` とラベル:**
`goto` 文とラベル定義をサポートし, 非線形な制御フローが可能です.
- **構造体と共用体のメンバアクセス**
ドット (`.`) とアロー (`->`) の両方に対応しています.
- **ビットフィールド**
構造体/共用体のビットフィールド宣言(ゼロ幅・無名フィールドを含む)を解析し, レイアウト計算に反映します(コード生成は未対応).
- **2進数・16進数リテラル**
例) `0b001011`, `0xFF2A`
- **コメント**
```c
// 1行コメント
/*
複数行コメント
*/
```
- `switch` 文と `case` / `default` ラベルをサポートし, 値に基づく分岐が可能です.
- 互換性のある型同士での明示的な型キャストをサポートしています.
- 三項演算子 (`?:`) に対応しており, インライン条件式を記述できます.
- `__asm__` などのインラインアセンブリはパースして無視します.
GNU/Clang 互換の `volatile` やクロバー指定を含む記法でもプリプロセッサが停止しなくなっています.
以下の機能には対応していません.
- `float`, `double` などの浮動小数点型(構文としては受け付けますが演算・コード生成は未実装)
- `register`, `auto` などの一部の型修飾子・ストレージ指定子
- 可変長引数関数 (`...`) の定義
- `va_list`, `va_start`, `va_arg` などのマクロはサポートされていません.
- ネストした関数定義
- 可変長配列 (VLA)
### 単一ユニットコンパイル
一度に扱えるのは単一の `.c` ファイルのみで, 複数ファイルの同時コンパイルには対応していません.
それぞれの `.c` ファイルを LaCC によりコンパイルした後に, `clang` や `gcc` によってリンクしてください.
### 最適化
LaCC は AST を制御フローグラフを持つ MIR(中間表現)へ変換してから
アセンブリを出力します. ローカル変数のスタックオフセットは MIR 最適化後に
確定するため, 最適化で消えた変数のための無駄なスタック領域は残りません.
最適化レベルに応じて, 次の処理を行います.
- **`-O0`**
- ローカル変数をメモリ上に保持し, SSA 最適化は行いません.
- MIR の仮想レジスタには生存解析と線形走査レジスタ割り当てを使用します.
- パーサーでの定数畳み込みや, 即値オペランドの利用などの局所的な命令選択は行います.
- **`-O1`**
- 未到達の基本ブロックを削除します.
- 支配関係と支配領域を計算し, phi ノードを配置して MIR を SSA 形式へ変換します.
- アドレスを取得されないスカラーのローカル変数を SSA 値へ昇格します (mem2reg).
- SSA 上でコピー・phi の伝播と, 副作用のない未使用値の削除を行います.
- 命令出力前に phi ノードを並列コピーへ戻します.
- CFG 生存解析から干渉グラフを構築し, コピー優先を考慮したグラフ彩色レジスタ割り当てとスピルを行います.
両レベルで未到達の内部関数を出力せず, MIR から参照されるローカル変数だけにスタック領域を割り当て, レジスタ割り当て後にスピル領域を確保します.
`-O` は現在 `-O1` と同等です.
`-O2` 以上の独自最適化レベルは未提供です.
最適化結果(命令行数)の比較には, 次のターゲットが使えます.
```bash
make asmcmp
```
MIR とレジスタ割り当てのデバッグ出力には, 次の環境変数が使えます.
```bash
LACC_DUMP_MIR=1 ./build/lacc -O1 -S foo.c -o foo.s
LACC_DUMP_RA=1 ./build/lacc -O1 -S foo.c -o foo.s
LACC_DUMP_RA=1 LACC_DUMP_RA_FN=main ./build/lacc -O1 -S foo.c -o foo.s
```
## 使用方法
### 1. リポジトリをクローンしてディレクトリに移動する
```bash
git clone https://github.com/Latte72R/LaCC
cd LaCC
```
この操作では, リポジトリをローカルに複製し, 作業ディレクトリを `LaCC` に変更します.
これにより, コンパイラをビルドしてテストするためのいくつかの `make` ターゲットが利用可能になります.
### 2. セルフホストコンパイラをビルドする
```bash
make selfhost
```
この操作では, `bootstrap`(ブーストラップコンパイラ)を使ってソースコードを再コンパイルし,
`lacc`(セルフホストコンパイラ)を生成します.
これにより, コンパイラのソースコード自体を正しくコンパイルできることを確認できます.
### 3. セルフホストコンパイラでプログラムを実行する
```bash
make run FILE=./examples/lifegame.c
make run FILE=./examples/rotate.c
```
これらのコマンドを実行することで, `lacc` を使って指定した C 言語のプログラムをコンパイルし実行できます.
### 4. セルフホストコンパイラのユニットテストを実行する
```bash
make unittest
```
すべてのテストが通れば, セルフホストコンパイラの動作が期待どおりであることが確認できます.
ユニットテストは `tests/unittest.c` にあります.
### 5. セルフホストコンパイラの警告テストを実行する
```bash
make warntest
```
このコマンドは警告テストを実行し, コンパイラが警告を正しく特定し報告できることを確認します.
警告テストは `tests/warntest.c` にあります.
### 6. セルフホストコンパイラのエラーテストを実行する
```bash
make errortest
```
このコマンドはエラーテストを実行し, コンパイラがエラーを正しく特定し報告できることを確認します.
エラーテストは `tests/errortest.sh` にあります.
### 7. ビルド成果物をクリーンアップする
```bash
make clean
```
このコマンドを実行することで, ビルド時に生成したバイナリやアセンブリファイルなどをすべて削除できます.
### 8. ヘルプを表示する
```bash
make help
```
利用可能な make ターゲットとその説明のリストを表示します.
## 作者について
LaCC は学生エンジニア **Latte72** が設計・開発しています!
### リンク
- **Web サイト:** [https://latte72.net/](https://latte72.net/)
- **GitHub:** [@Latte72R](https://github.com/latte72r)
- **X (a.k.a Twitter):** [@Latte72R](https://twitter.com/Latte72R)
- **Qiita:** [@Latte72R](https://qiita.com/latte72r)