Releases: shadowlink0122/Cm
v0.15.0
title: v0.15.0
parent: Release Notes
nav_order: 1
Cm v0.15.0 リリースノート
リリース日: 2026-03-09
前バージョン: v0.14.2
✨ ハイライト
v0.15.0はSystemVerilog (SV) バックエンドの本格実装とプラットフォームディレクティブによるレキサーモード分離を含むメジャーアップデートです。CmからFPGA向けのSystemVerilogコードを生成し、iverilogによるシミュレーション検証まで一貫して実行可能になりました。
🔧 SystemVerilogバックエンド(新規)
Phase 1-5: コア実装
MIRからSystemVerilogへの変換パイプラインを実装。構造化CFG走査により、MIRの基本ブロックからif/else/case等のSV制御構文を正確に再構築します。
cm compile --target=sv program.cm -o output.svポート宣言と回路タイプ
| アトリビュート | 生成されるSV |
|---|---|
#[input] |
input logic [N:0] name |
#[output] |
output logic [N:0] name |
| 通常関数 | always_comb begin ... end |
posedge型引数 |
always_ff @(posedge clk) begin ... end |
negedge型引数 |
always_ff @(negedge clk) begin ... end |
SV固有型(文脈キーワード)
posedge、negedge、wire、reg型をCm言語レベルで直接サポート。SVプラットフォーム時のみキーワードとして認識され、非SVモードでは通常の識別子として使用可能。
SV幅付きリテラル
SystemVerilog形式の幅付きリテラル(N'd, N'b, N'h)をCmパーサーで直接サポート。Token→AST→HIR→MIR→SV codegen の全段で元のベース形式を保持して出力します。
out = 3'b101; // → 3'b101 (2進数)
out = 8'hFF; // → 8'hFF (16進数)
out = 8'd170; // → 8'd170 (10進数)
一時変数の最適化
MIR→SV変換時に一時変数(_tXXXX)をインライン展開し、使用されなくなった変数のlogic宣言を自動除去。クリーンなSV出力を実現。
三項演算子の自動最適化
if/elseが同一変数への単一代入のみの場合、cond ? a : b に自動変換。合成ツールの効率向上と可読性改善。
テストベンチ自動生成
cm compile --target=sv実行時にiverilog互換のテストベンチ(_tb.sv)を自動生成。
その他の機能
| 機能 | 説明 |
|---|---|
| BRAM推論 | 配列をBlock RAMとして推論 |
| マルチクロックドメイン | sv::clock_domain(clk_name)アトリビュート |
| XDC制約ファイル生成 | sv::pinアトリビュートでピン配置指定 |
| 非ブロッキング代入 | 順序回路で<=を自動使用 |
🆕 プラットフォームディレクティブ
ソースファイル先頭の //! platform: sv ディレクティブまたは --target=sv CLIオプションにより、レキサーのキーワードテーブルをプラットフォームごとに切り替える仕組みを導入。
//! platform: sv
// posedge/negedge/wire/reg がキーワードトークンとして認識される
| モード | キーワード追加 | 用途 |
|---|---|---|
LexerPlatform::Default |
なし | 通常のCmコード |
LexerPlatform::SV |
posedge, negedge, wire, reg |
SVターゲット |
🐛 バグ修正
| 問題 | 修正内容 |
|---|---|
| 型キーワードnamespace関数呼び出し失敗 | parse_namespace()/current_text()でget_string()→token_kind_to_string()に修正 |
| posedge等が非SVコードで型消費 | parse_type()のIdentテキスト比較ブロック削除、レキサーKwトークンに完全移行 |
| rstポート挿入位置 | clk実位置を検索して直後に挿入するよう修正 |
| 非合成型チェック未呼び出し | compile()からvalidateSynthesizableTypes()を呼び出し、エラー時にコンパイル中止 |
| parameter二重宣言 | sv::param変数がparameter/logicで二重定義されるバグを修正 |
| SV幅付きリテラル例外クラッシュ | stoi/stoullをtry-catchで保護、値部空チェック・基数文字検証を追加 |
| グローバル変数初期化子省略範囲 | SVポート型/アトリビュートのみ省略可能に限定 |
⚡ ビルド高速化
| 変更 | 説明 |
|---|---|
| ccache自動検出 | インストール済みなら自動でコンパイルキャッシュ有効化 |
| Unity build | ソースファイル結合(バッチ16)でヘッダパース回数を大幅削減 |
| SV生成物管理 | デフォルトSV出力を.tmp/配下に変更、ルートディレクトリの汚染を防止 |
| コンパイラ警告0件達成 | 符号比較・演算子優先順位・未使用変数の警告を全解消 |
| Token/AST/HIR/MIR最適化 | SV幅付きリテラル情報をstd::optional<BitLiteralInfo>に統一 |
🎨 VSCode拡張機能
SV幅付きリテラルのハイライト
N'[dbh]VALUEパターンをconstant.numeric.sv-literal.cmスコープとして認識。8'hFF等が文字リテラルではなく数値リテラルとしてハイライトされるよう修正。
文字リテラルパターン修正
シングルクォートの文字リテラルを'X'(1文字のみ)にマッチするmatchパターンに変更。
🧪 テスト基盤
テストディレクトリ統合
tests/programs/を廃止し、全テストをtests/直下のカテゴリディレクトリに統合。
SVテストの並列実行
unified_test_runner.shのrun_parallel_testにSVバックエンドを追加。make tsvpでiverilogシミュレーション検証を含む全SVテストを並列実行可能に。
CIへのSVテスト・iverilog追加
GitHub Actions CIにiverilogのインストールとSVシミュレーション検証を追加。macOSでのbrew install失敗時はwarning出力+SVテストスキップへ明示的分岐。
テストカバレッジ
| カテゴリ | テスト数 |
|---|---|
| sv/advanced | 6 (fsm, led_blinker, multi_clock, negedge_reset, parameterized, posedge_counter) |
| sv/basic | 11 (adder, arithmetic, binary_bits, bitwise, counter, multi_expr, mux, shift, sv_width_literal, ternary, unary) |
| sv/control | 5 (compare, nested_if, priority_encoder, shift_register, signed_ops) |
| sv/memory | 1 (bram) |
| 合計 | 23テスト |
📁 主要な変更ファイル
| ファイル | 変更内容 |
|---|---|
src/codegen/sv/codegen.cpp |
SVコード生成エンジン全体 |
src/frontend/lexer/lexer.hpp |
LexerPlatform enum、add_sv_keywords()定義 |
src/frontend/lexer/lexer.cpp |
SVキーワード動的追加、プラットフォームディレクティブ検出 |
src/frontend/parser/parser_type.cpp |
SV Identテキスト比較ブロック削除 |
src/frontend/parser/parser_module.cpp |
namespace名取得のget_string()修正 |
src/frontend/parser/parser_expr.cpp |
SV幅付きリテラル・型キーワード名前空間修飾 |
vscode-extension/syntaxes/cm.tmLanguage.json |
SV幅付きリテラルハイライト |
.github/workflows/ci.yml |
SVテスト+iverilog追加 |
tests/unified_test_runner.sh |
SVテスト並列実行対応 |
📊 テスト結果
| バックエンド | 通過 | 失敗 | スキップ |
|---|---|---|---|
| JIT (O0) | 368 | 0 | 5 |
| SV | 23 | 0 | 0 |
📖 ドキュメント
- 新規チュートリアル: SVバックエンド (ja/en)
- 設計書更新: SV設計書2件をPhase 1 IMPLEMENTED、他3件のステータスを更新
🔮 今後の予定
- v0.16.0: 型同一性改善、メソッドチェーン型チェッカー拡張、モジュール分離コンパイル
v0.14.2
title: v0.14.2
parent: Release Notes
nav_order: 1
Cm v0.14.2 リリースノート
リリース日: 2026-03-07
前バージョン: v0.14.1
✨ ハイライト
v0.14.2はTagged Union(Result/Option/enum)のペイロード抽出に関する重大バグ2件の修正、ASM過剰volatile生成の修正、Dead Function Elimination(DFE)の追加、__asm__定数展開、モノモーフィゼーション最適化を含むパッチリリースです。ベアメタル環境でのResult型エラーハンドリングを安全に使用可能にし、コンパイル・テスト性能を改善しました。
🐛 重大バグ修正: Tagged Union ペイロード
Bug#1: ペイロード型の64bitハードコード問題
mir_to_llvm.cppのconvertPlaceToAddressでTagged Union(enum/Result/Option)のペイロード型がhir::make_int()(i32)にハードコードされ、64bit型のペイロードが切り詰められる問題。
| 項目 | 詳細 |
|---|---|
| 症状 | Result::Ok(0)のペイロード抽出で188050848088064等の不正値 |
| 原因 | ペイロード型がi32固定 → 64bit値の上位4バイトが未読 |
| 修正 | type_argsから動的にペイロード型を推論、64bit型存在時はi64を使用 |
| テスト | JIT 365 PASS / LLVM 399 PASS、回帰なし |
Bug#2: ペイロード部分書き込みによるundef bytes
Result::Ok(0)等のenum construct時、ペイロード値(i32)がi8[N]に部分書き込みされ、LLVM最適化がmemset+storeをconstant phiに畳み込む際にundef bytesが生成される問題。
| 項目 | 詳細 |
|---|---|
| 症状 | ベアメタル環境でResult<ulong, long>::Ok(0)の値にゴミデータ混入 |
| 原因 | ペイロードストアが32bitのみ→残りバイトがundefined |
| 修正1 | payload storeにZExt(Zero-Extension)を追加し正確なビット幅に拡張 |
| 修正2 | retval allocaにstruct型ゼロ初期化を追加 |
| 修正3 | resolve_typedefにモノモーフ化enum名フォールバック追加 |
影響: この修正により
Result<T, E>でT==E(例:Result<long, long>)が正しく動作。ベアメタル環境を含む全レイヤーでResult型エラーハンドリングが使用可能に。
🐛 その他のバグ修正
ASM含有関数の過剰volatile生成
__asm__を含む関数で全ローカル変数にvolatile属性が付与され、不要なalloca → volatile store → volatile loadチェーンが生成される問題を修正。
修正前: outb(ushort, utiny) → 13回のメモリ操作、0x43バイト
修正後: outb(ushort, utiny) → 0回のメモリ操作、0x4バイト
型キーワードのnamespace名衝突
import ../lib/string;で展開されるnamespace string { ... }がCm組み込み型stringと衝突する問題を修正。
その他
| 問題 | 修正内容 |
|---|---|
| varargs関数のパラメータ数検証 | 最小引数数でのガードに修正 |
| callee関数のシンボル検索失敗 | impl内関数のルックアップロジック修正 |
| 文字列スライスの範囲外アクセス | スライス境界チェック追加 |
| プリプロセッサのデバッグログ | debug_modeガードで保護 |
| パーサ無限再帰 | 安全ガード追加 |
| DFEラムダ関数誤削除 | ラムダ関数をDFEスキップ対象に追加 |
| interface impl関数のDCE除去 | 未使用誤判定の修正 |
| フォーマッター | バッククォートインデント崩壊修正、括弧内継続行修正 |
✨ 新機能
Dead Function Elimination (DFE)
MIR→LLVM変換時に未使用関数を除去する最適化パスを追加。ベアメタル環境でのバイナリサイズ削減に有効。
enum値の文字リテラルサポート
parse_enum_declでCharLiteralを受け付けるよう拡張。
export enum Ascii {
LowerA = 'a',
LowerB, // 98 (オートインクリメント)
UpperA = 'A',
Digit0 = '0',
}
__asm__内の${CONST_NAME}定数展開
lower_asmでasm文字列中の${CONST_NAME}パターンを検出し、global_const_valuesテーブルから定数値を取得して16進数リテラルに直接置換。colonを含む${+r:var}等のオペランド記法はスキップ。
x86_64 Dockerクロスビルド対応
x86_64ターゲット向けDockerビルド環境を追加。LLVM共有ライブラリ + C++静的リンクの最適構成。
⚡ パフォーマンス改善
モノモーフィゼーション反復ループ最適化
| 項目 | 旧 | 新 |
|---|---|---|
| 最大反復数 | 10パス (全関数フルスキャン) | 2パス (2パス目は新規関数のみ) |
monomorphize_structs() |
2回実行 | 1回に統合 |
ネストジェネリクス(Queue等)にも対応。
テストランナー並列化改善(FIFOセマフォ方式)
| 項目 | 旧 | 新 |
|---|---|---|
| 同期方式 | PIDポーリング (kill -0 + sleep 0.05) |
FIFOセマフォ (mkfifo + fd) |
| max_jobs | CPU数 | CPU数×4 (I/Oバウンド考慮) |
| 実行時間 | 1:57 | 51.5s (55%短縮) |
| CPU使用率 | 100% | 232% |
📁 主要な変更ファイル
| ファイル | 変更内容 |
|---|---|
src/codegen/llvm/core/mir_to_llvm.cpp |
ASM volatile修正、DFE連携、64bit payload型推論、ZExtストア、retvalゼロ初期化 |
src/mir/lowering/base.cpp |
resolve_typedefモノモーフ化enum名フォールバック |
src/mir/lowering/context.cpp |
resolve_typedef enum_defs検索フォールバック |
src/mir/lowering/stmt.cpp |
__asm__内${CONST_NAME}定数展開 |
src/mir/passes/cleanup/program_dce.cpp |
Dead Function Elimination実装 |
src/mir/passes/monomorphization_impl.cpp |
モノモーフ反復ループ2パス最適化 |
src/frontend/parser/parser_expr.cpp |
型キーワード名前空間修飾子対応 |
src/frontend/parser/parser_module.cpp |
enum値CharLiteralサポート、無限再帰ガード |
src/frontend/types/checking/stmt.cpp |
Tagged Union 64bitペイロード型チェック |
src/fmt/formatter.cpp |
バッククォート+括弧継続行修正 |
tests/unified_test_runner.sh |
FIFOセマフォ並列化 (55%短縮) |
Dockerfile |
x86_64クロスビルド環境 (新規) |
📊 テスト結果
| バックエンド | 通過 | 失敗 |
|---|---|---|
| JIT (O0) | 365 | 0 |
| LLVM Native | 399 | 0 |
| Baremetal | 全通過 | 0 |
🔮 今後の予定
- v0.15.0: File I/O、パッケージ管理、JSバックエンドのポインタ/VTable対応
v0.14.1
title: v0.14.1
parent: Release Notes
nav_order: 1
Cm v0.14.1 リリースノート
リリース日: 2026-02-19
最終更新: 2026-02-21
✨ ハイライト
v0.14.1はUEFIコンパイラバグ17件の修正、typedef算術演算サポート、GCC/Linux CIビルド修正を含むパッチリリースです。CosmOS UEFI開発で発見されたコンパイラバグを全件修正し、MIR最適化パスのASM対応、naked関数コード生成の根本修正など広範な安定化を実施しました。
🐛 UEFIコンパイラバグ全件修正(Bug#1〜#17)
CosmOS UEFI開発中に発見されたコンパイラバグ17件を全て修正しました。
| Bug# | 問題 | 重要度 | 修正内容 | 回帰テスト |
|---|---|---|---|---|
| #1 | 3引数関数でのポインタ破損(Win64呼出規約) | 重大 | 全関数にWin64呼出規約を設定 | uefi_struct |
| #2 | *ptr as ulongデリファレンスエラー |
— | 仕様通り(括弧付きで正常) | — |
| #5 | LICM最適化がASM出力変数を移動 | 重大 | ASM出力変数のループ不変判定修正 | uefi_bug5_direct |
| #6 | constant foldingのASM出力追跡 | 重大 | ASM→変数代入チェーン最適化抑制 | uefi_asm_while |
| #7 | must{__asm__()}の制御フロー干渉 |
低 | 全ASMにhasSideEffects+クロバー設定 | uefi_bug7_* |
| #8 | const式でのI/Oポート計算 | 中 | const式評価パイプライン修正 | uefi_arithmetic |
| #9 | ローカル配列のスタックオフセット重複 | 重大 | alloca skipルール削除+array-to-pointer decay | uefi_bug9_array_ptr |
| #10 | ptr->method()のself書き戻し不在 |
重大 | MIR loweringでポインタ経由書き戻し実装 | impl_nested_self, impl_ptr_self |
| #11 | インライン展開によるASMレジスタ割当変更 | 重大 | ASM含有関数にNoInline属性付与 | uefi_bug11_asm_func |
| #12 | インライン展開時のret先不在 | 重大 | Naked+$N事前置換方式に統一 | uefi_bug12_asm_ret |
| #13 | インライン展開時のレジスタ上書き(クラッシュ) | 致命的 | UEFI全関数NoInline+efi_mainにOptimizeNone | uefi_impl_inline |
| #14 | 構造体配列の全体再代入でゴミ値 | 重大 | memcpy/配列代入の型サイズ修正 | uefi_large_impl |
| #15 | 非export関数がexport関数から呼出不可 | 中 | シンボル解決(extract_exported_blocks)修正 | uefi_cross_module_call |
| #16 | &local as ulongキャスト不正 |
低 | ポインタ→整数キャスト修正 | uefi_pointer_cast |
| #17 | UEFIスタックプローブクラッシュ | 中 | スタックプローブの無効化 | uefi_stack_probe |
🔧 言語機能の修正
修正済みバグ(6件)
| 問題 | 修正内容 | 回帰テスト |
|---|---|---|
| typedef算術演算エラー | typedef型のis_numeric判定修正 | typedef_compound_assign |
| typedef引数の型不整合 | static→static呼び出し時の型解決 | typedef_struct_param |
| GCC CIビルドエラー | <unordered_map>ヘッダー追加 |
CI自動テスト |
| 大きな16進リテラルのprintln | println関数選択にlong/ulong追加 | ulong_large_hex |
| ビット演算の型幅不一致 | BitAnd/BitOr/BitXorに型統一ロジック追加 | operator_bitwise |
| ASM関数のインライン展開 | ASM含有関数のインライン展開禁止 | uefi_bug11_asm_func |
typedef算術演算サポート
typedef型の値に対する算術演算・比較演算が正常に動作するようになりました。
typedef EFI_STATUS = ulong;
EFI_STATUS status = 0;
if (status != 0) { /* 修正前: コンパイルエラー → 修正後: 正常動作 */ }
整数型出力の完全対応
MIR loweringのprintln関数選択ロジックにlong/ulong/uint/isize/usize型のケースを追加。i32範囲を超える値が正しく出力されるようになりました。
long v = 0x80000000; // 2147483648
println(v); // 修正前: -2147483648 (i32切り詰め)
// 修正後: 2147483648 (正しい出力)
🏗️ バックエンド改善
GCC/Linux CIビルド修正
src/mir/nodes.hppに<unordered_map>ヘッダーを追加。AppleClangでは間接インクルードで解決されていたが、GCCでは明示的なインクルードが必要でした。
JS/WASMランタイム改善
| ファイル | 変更内容 |
|---|---|
src/codegen/js/builtins.cpp |
cm_println_long/ulong/uintとformat/to_string版追加 |
src/codegen/llvm/wasm/runtime_print.c |
cm_println_long/ulong出力関数追加 |
src/codegen/llvm/core/operators.cpp |
ビット演算(BitAnd/BitOr/BitXor)の型幅統一ロジック追加 |
src/mir/passes/interprocedural/inlining.cpp |
ASM含有関数のインライン展開禁止 |
MIR最適化パスのASM対応
| パス | 修正内容 |
|---|---|
| LICM (Loop Invariant Code Motion) | ASM出力変数をループ不変と誤判定しない修正 |
| Constant Folding | ASM→変数代入チェーンの最適化を抑制 |
| Constant Folding | 構造体フィールドアクセスの最適化を抑制 |
| Inlining | ASM含有関数のインライン展開を禁止 |
📁 主要な変更ファイル
| ファイル | 変更内容 |
|---|---|
src/codegen/llvm/core/mir_to_llvm.cpp |
Bug#1/7/8/11/12/14/16修正、naked関数統一 |
src/codegen/llvm/native/codegen.cpp |
Bug#13/17: UEFI最適化レベル調整、スタックプローブ無効化 |
src/mir/lowering/expr_call.cpp |
println型選択にlong/ulong/uint/isize/usize追加 |
src/mir/lowering/stmt.cpp |
Bug#10: ptr->method()のself書き戻し |
src/mir/lowering/monomorphization_impl.cpp |
typedef引数の型解決修正 |
src/mir/passes/scalar/folding.cpp |
Bug#6/9: ASM出力・構造体フィールド最適化抑制 |
src/mir/passes/loop/licm.cpp |
Bug#5: ASM出力変数のループ不変判定修正 |
src/mir/nodes.hpp |
GCC CIビルド修正(unordered_mapヘッダー追加) |
src/frontend/types/checking/expr.cpp |
typedef算術演算サポート |
src/preprocessor/import.cpp |
Bug#15: 非export関数のシンボル解決修正 |
🧪 リグレッションテスト
UEFIコンパイルテスト(20件)
| テストファイル | 対象バグ/機能 |
|---|---|
uefi_arithmetic.cm |
Bug#8: const式計算 |
uefi_asm_scratch_reg.cm |
ASMスクラッチレジスタ |
uefi_asm_while.cm |
Bug#6: ASMループ |
uefi_bug5_direct.cm |
Bug#5: LICM最適化 |
uefi_bug7_compiler_barrier.cm |
Bug#7: コンパイラバリア |
uefi_bug7_must_hlt.cm |
Bug#7: must+hlt |
uefi_bug9_array_ptr.cm |
Bug#9: 配列ポインタ |
uefi_bug11_asm_func.cm |
Bug#11: ASM関数 |
uefi_bug12_asm_ret.cm |
Bug#12: naked関数 |
uefi_control_flow.cm |
制御フロー |
uefi_cross_module_call.cm |
Bug#15: クロスモジュール |
uefi_export_many.cm |
Bug#14: export数 |
uefi_impl_inline.cm |
Bug#13: インライン展開 |
uefi_large_impl.cm |
Bug#14: 大構造体 |
uefi_must_asm.cm |
must+ASM |
uefi_naked_mixed_func.cm |
naked混在関数 |
uefi_pointer_cast.cm |
Bug#16: ポインタキャスト |
uefi_stack_large.cm |
大スタック |
uefi_stack_probe.cm |
Bug#17: スタックプローブ |
uefi_struct.cm |
Bug#1: 構造体 |
JIT/LLVM回帰テスト(主要)
| テストファイル | 対象 |
|---|---|
impl_nested_self.cm |
Bug#10: ネストself |
impl_nested_self_deep.cm |
Bug#10: 深いネスト |
impl_ptr_self.cm |
Bug#10: ポインタself |
impl_ptr_large_struct.cm |
Bug#10: 大構造体 |
while_sccp_regression.cm |
Bug#5: SCCP回帰 |
ptr_to_int_cast.cm |
Bug#16: ポインタ→整数 |
typedef_compound_assign.cm |
typedef算術 |
operator_bitwise.cm |
ビット演算 |
📊 テスト結果
| バックエンド | 通過 | 失敗 | スキップ |
|---|---|---|---|
| JIT (O0) | 347 | 0 | 4 |
| LLVM Native | 380 | 0 | 7 |
| LLVM WASM | 346 | 0 | 5 |
| JavaScript | 306 | 0 | 49 |
| Baremetal | 11 | 0 | 0 |
| UEFI | 20 | 0 | 0 |
⚠️ 既知の制約事項(UEFIターゲット固有)
以下はUEFIバックエンド固有の制約であり、JIT/LLVM Native/WASM/JSでは発生しません。
全件に回避策があり、CosmOS開発で実証済みです。
| # | 制約 | 回避策 |
|---|---|---|
| 5 | ASM出力変数のwhile条件不具合 | ループ内でスコープ宣言+break |
| 7 | must{__asm__()}の制御フロー干渉 |
mustなしで直接使用 |
| 9 | ローカル配列+ポインタ変数のオフセットずれ | アドレスを変数に格納しない |
| 11 | ABIレジスタ直接参照の不正動作 | ${r:var}構文を使用 |
| 12 | インライン展開時のret先不在 | 数値ラベルでreturn address push |
| 17 | ___chkstk_ms未定義シンボル |
no-opスタブをリンク |
注: これらの制約はCmコンパイラのUEFIバックエンド固有の問題であり、
JITモード(cm run)では再現しません。将来のリリースで改善予定です。
🔮 今後の予定
- v0.15.0: File I/O、パッケージ管理、JSバックエンドのポインタ/VTable対応、UEFI/ベアメタルの拡充
v0.14.0
title: v0.14.0
parent: Release Notes
nav_order: 1
Cm v0.14.0 リリースノート
リリース日: 2026-02-15
✨ ハイライト
v0.14.0は、JavaScriptバックエンドの大規模改善、演算子オーバーロードの設計改善、ベアメタル/UEFIサポート、インラインユニオン型 (int | null) の実装、プラットフォームディレクティブの導入を含むリリースです。JSバックエンドのテスト通過率が55%から87%に向上し、演算子オーバーロードではimpl T構文と複合代入演算子(+=等)をサポートしました。また、UEFIターゲットでのベアメタル開発が可能になりました。
主要な変更点
- JSバックエンド大規模リファクタリング: codegen.cppから1,600行以上を削り、モジュール分割でコード品質を向上
- JSテスト通過率向上: 55% → 87%(206/372 → 298/347)
- 演算子オーバーロード改善:
impl T { operator ... }構文で直接演算子定義が可能に - 複合代入演算子:
+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=をサポート - ビット演算子オーバーロード:
&,|,^,<<,>>のカスタム定義に対応 - インラインユニオン型:
int | nullのようなインラインユニオン構文を導入 - null型: 独立した
null型を追加(TypeKind::Null) - プラットフォームディレクティブ:
//! platform:でファイルレベルの実行環境制約を指定 - ベアメタル/UEFIサポート:
--target=uefiでUEFI Hello Worldが動作、QEMUで出力確認済み - インラインASM自動クロバー検出: ハードコードレジスタの自動検出でインライン展開時のバグを防止
- Enum Associated Data修正: 文字列・構造体ペイロードの
println出力が正常に動作 - Tagged Union構造体ペイロードサイズ修正: 3フィールド以上の構造体ペイロードの破損を修正
- interface存在チェック:
impl T for IのIが宣言済みinterfaceであることを検証
🚀 JSバックエンド改善
codegen.cppの大規模リファクタリング
JSコードジェネレータを大幅にリファクタリングし、コードの保守性と品質を向上させました。
| 変更 | 詳細 |
|---|---|
| codegen.cpp | -1,618行(不要なコード削除・整理) |
| emit_expressions.cpp | +124行(式の出力改善) |
| emit_statements.cpp | +80行(文の出力改善) |
| builtins.hpp | +71行(ビルトイン関数マッピング拡充) |
| runtime.hpp | +19行(ランタイムヘルパー追加) |
| types.hpp | +9行(型マッピング改善) |
JSテスト通過率
| バージョン | パス | 失敗 | スキップ | 通過率 |
|---|---|---|---|---|
| v0.13.1 | 206 | 119 | 47 | 55% |
| v0.14.0 | 298 | 0 | 49 | 87% |
失敗テスト: 119 → 0(未対応テストは適切にスキップに移行)
JSコンパイルの使い方
# JSへコンパイル
./cm compile --target=js hello.cm -o output.js
# 実行
node output.js詳細は JSコンパイルチュートリアル を参照してください。
🐛 バグ修正
Enum Associated Dataのprintln出力修正
match armのペイロード変数をprintlnで出力する際、ランタイムハングや不正な出力が発生するバグを修正しました。
enum Message {
Quit,
Write(string)
}
int main() {
Message m = Message::Write("Hello");
match (m) {
Message::Write(t) => {
println(t); // v0.13.1: ハング → v0.14.0: "Hello"
}
_ => {}
}
return 0;
}
| 問題 | 原因 | 修正ファイル |
|---|---|---|
| println型判定の誤り | AST型チェッカーがmatch armのpayload変数の型をintに設定 |
expr_call.cpp |
| ペイロードロードエラー | Tagged Unionの非構造体ペイロードの型がi32にハードコード |
mir_to_llvm.cpp |
Tagged Union構造体ペイロードのサイズ修正
3フィールド以上の構造体をenumペイロードに格納すると、3番目以降のフィールドが破損するバグを修正しました。
struct RGB {
int r;
int g;
int b;
}
enum Color {
None,
Set(RGB)
}
int main() {
Color c = Color::Set(RGB { r: 255, g: 128, b: 0 });
match (c) {
Color::Set(v) => {
println("RGB({v.r}, {v.g}, {v.b})");
// v0.13.1: RGB(255, 128, 1) ← b=0が1に破損
// v0.14.0: RGB(255, 128, 0) ← 正常
}
_ => {}
}
return 0;
}
| 問題 | 原因 | 修正ファイル |
|---|---|---|
| 構造体3番目以降のフィールドが破損 | max_payload_size()がStruct型をデフォルト8バイトで計算 |
types.cpp |
修正: LLVM DataLayoutを使用して構造体型のサイズを正確に計算するよう変更。
🎼 演算子オーバーロード改善
impl T { operator ... } 構文
演算子を impl T for InterfaceName ではなく、直接 impl T { operator ... } で定義可能になりました。
struct Vec2 {
int x;
int y;
}
impl Vec2 {
operator Vec2 +(Vec2 other) {
return Vec2{x: self.x + other.x, y: self.y + other.y};
}
operator Vec2 -(Vec2 other) {
return Vec2{x: self.x - other.x, y: self.y - other.y};
}
}
複合代入演算子
二項演算子を定義すると、対応する複合代入演算子(+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=)が自動的に使えます。
int main() {
Vec2 v = Vec2{x: 10, y: 20};
v += Vec2{x: 5, y: 3}; // Vec2{15, 23}
v -= Vec2{x: 2, y: 1}; // Vec2{13, 22}
return 0;
}
ビット演算子オーバーロード
&, |, ^, <<, >> の全ビット演算子をオーバーロード可能になりました。
interface存在チェック
impl T for I 構文で I が宣言済みinterfaceでない場合、コンパイルエラーになります。これにより、マジックストリング(impl T for Add 等)によるバグを防止します。
🧬 インラインユニオン型とnull型
インラインユニオン構文 (int | null)
インラインユニオン構文(|)でnull許容型を表現できるようになりました。
import std::io::println;
// typedefのユニオン型は従来通り
typedef MaybeInt = int | null;
// インラインユニオン型: typedefなしで直接型を結合
int main() {
int | null a = null; // nullが代入可能
int | null b = 42 as MaybeInt; // int値も代入可能
int | string | null c = null; // 3型以上のユニオンも可能
return 0;
}
| 変更 | 詳細 |
|---|---|
null型追加 |
TypeKind::Null、make_null() |
parse_type_with_union() |
変数宣言・関数戻り値・構造体フィールドで使用 |
| 型互換性 | Unionメンバー型とのnull代入・値代入に対応 |
注意: operator戻り値型では
|がビットOR演算子と競合するため、インラインユニオンは使用できません。typedefを使用してください。
🌍 プラットフォームディレクティブ
ファイル先頭に //! platform: ディレクティブを記述することで、そのファイルが実行可能なプラットフォームを制約できます。
//! platform: native
// このファイルはLLVM Native/JITでのみコンパイル可能
import std::io::println;
int main() {
println("Native only");
return 0;
}
対応プラットフォーム: native, js, wasm, uefi, baremetal
🔧 ビルド・テスト改善
JSスキップファイルの整理
JSバックエンドで未サポートのネイティブAPI機能カテゴリに.skipファイルを追加:
| カテゴリ | 理由 |
|---|---|
asm/ |
インラインアセンブリはJS非対応 |
io/ |
ファイルI/OはJS非対応 |
net/ |
TCP/HTTPソケットはJS非対応 |
sync/ |
Mutex/Channel/AtomicはJS非対応 |
thread/ |
スレッドはJS非対応 |
reimportテストの修正
advanced_modules/reimport.cmテストの出力を修正し、NativeとJSの両方で正しい結果を出力するようにしました。
不安定テストの分割
macOSで不安定なoperator_comprehensiveテストを5つの個別テストに分割し、問題の切り分けを可能にしました:
operator_arithmetic— 算術演算子 (+, -, *, /, %)operator_compare— 比較演算子 (==, !=, <, >)operator_bitwise— ビット演算子 (&, |, ^, <<, >>)operator_compound_assign— 算術複合代入 (+=, -=, *=, /=, %=)operator_bitwise_assign— ビット複合代入 (&=, |=, ^=, <<=, >>=)
⚡ パフォーマンス改善
コンパイル速度の大幅改善
MIR最適化パイプラインとキャッシュデフォルトの見直しにより、コンパイル時間を大幅に削減しました。
| 項目 | 改善前 | 改善後 | 削減率 |
|---|---|---|---|
| UEFIコンパイル | 2764ms | 646ms | 76%削減 |
| MIR最適化 | 593ms | 389ms | 34%削減 |
主な変更点:
- キャッシュ(インクリメンタルビルド)をデフォルト無効化(
--incrementalで明示的に有効化可能) - MIR最適化パイプラインに「前回変更なしパスのスキップ」ロジックを追加
- SCCPに小規模関数の早期リターンを追加
🖥️ ベアメタル / UEFI サポート
UEFI Hello World
--target=uefi オプションでUEFIアプリケーションをコンパイルできるようになりました。OSなし(no_std)のベアメタル環境で動作し、QEMU + OVMFで「Hello World from Cm!」の出力を確認しています。
# UEFIアプリケーションのビルド
cm compile --target=uefi -o hello.o hello_world.cm
lld-link /subsystem:efi_application /entry:efi_main /out:BOOTX64.EFI hello.o
# QEMUで実行
qemu-system-x86_64 -drive if=pflash,format=raw,readonly=on,file=OVMF.fd \
-drive format=raw,file=fat:rw:esp -net none -nographic// UEFI Hello World
import ./libs/efi_core;
import ./libs/efi_text;
ulong efi_main(void* image_handle, void* system_table) {
efi_clear_screen(system_table);
string msg = "Hello World from Cm!";
efi_println(system_table, msg as void*);
while (true) { __asm__("hlt"); }
return 0;
}
インラインASM自動クロバー検出
インラインアセンブリ内のハードコードレジスタ(%rax, %rcx, %rdi等)を自動検出し、LLVMクロバーリストに追加する機能を実装しました。これにより、インライン展開時にLLVMがASMで破壊されたレジスタの値を再利用するバグを防止します。
| 問題 | 原因 | 修正 |
|---|---|---|
| UEFI出力なし | ASMのハードコードレジスタがクロバー未宣言 | mir_to_llvm.cpp: 自動クロバー検出 |
| #GPクラッシュ | LLVMレジスタ割当とハードコードの競合 | efi_text.cm: pushq/popqパターン |
🛠️ VSCode拡張機能の改善
TypeScript移行
VSCode拡張機能のスクリプト(update-version, verify-version)をJavaScriptからTypeScriptに移行しました。strict modeで型安全性を確保しています。
ESLint + Prettier導入
拡張機能にESLint(Flat Config v9+)とPrettierを導入し、コード品質を自動チェックするようにしました。
| ツール | 設定 | コマンド |
|---|---|---|
| TypeScript | tsconfig.json (strict, ES2020) |
pnpm run compile |
| ESLint | eslint.config.mjs (typescript-eslint) |
pnpm run lint |
| Prettier | .prettierrc |
pnpm run format:check |
CI統合
ci.yml に extension-lint ジョブを追加。push/PRごとに以下を自動チェック:
- TypeScript compile
- ESLint check
- Prettier format check
📁 主要な変更ファイル
JSバックエンド
| ファイル | 変更内容 |
|---|---|
src/codegen/js/codegen.cpp |
大規模リファクタリング(-1,618行) |
src/codegen/js/emit_expressions.cpp |
式出力の改善 |
src/codegen/js/emit_statements.cpp |
文出力の改善 |
src/codegen/js/builtins.hpp |
ビルトイン関数マッピング拡充 |
src/codegen/js/runtime.hpp |
ランタイムヘルパー追加 |
src/codegen/js/types.hpp |
型マッピング改善 |
src/codegen/js/codegen.hpp |
ヘッダ追加 |
LLVMバックエンド修正
| ファイル | 変更内容 |
|---|---|
src/codegen/llvm/core/types.cpp |
Tagged Unionペイロードサイズ計算修正 |
src/codegen/llvm/core/mir_to_llvm.cpp |
ペイロードロード修正、デバッグ出力削除 |
MIR Lowering修正
| ファイル | 変更内容 |
|---|---|
src/mir/lowering/expr_call.cpp |
println型判定でMIRローカル型を優先 |
src/mir/lowering/impl.cpp |
impl lowering改善 |
テスト
| ファイル | 変更内容 |
|---|---|
tests/programs/interface/operator_arithmetic.* |
算術演算子テスト(分割) |
tests/programs/interface/operator_compare.* |
比較演算子テスト(分割) |
tests/programs/interface/operator_bitwise.* |
ビット演算子テスト(分割) |
tests/programs/interface/operator_compound_assign.* |
算術複合代入テスト(分割) |
tests/programs/interface/operator_bitwise_assign.* |
ビット複合代入テスト(分割) |
tests/programs/enum/associated_data.* |
新規(.error → .expected) |
tests/programs/asm/.skip 等 |
JSスキップファイル追加 |
tests/unified_test_runner.sh |
テストランナー改善 |
🧪 テスト状況
| バックエンド | 通過 | 失敗 | スキップ |
|---|---|---|---|
| JIT (O0) | 343 | 0 | 4 |
| LLVM Native | 343 | 0 | 4 |
| LLVM WASM | 338 | 0 | 5 |
| JavaScript | 298 | 0 | 49 |
📊 統計
- テスト総数: 347
- JIT/LLVMテスト通過: 343(0失敗)
- WASMテスト通過: 338(0失敗)
- JSテスト通過: 298(0失敗、v0.13.1の206から+92改善)
- UEFIテスト: QEMUでHello World出力確認済み
🔮 今後の予定
- v0.15.0: File I/O、パッケージ管理、JSバックエンドのポインタ/V...