Cm v0.14.0 リリースノート

リリース日: 2026-02-10

✨ ハイライト

v0.14.0は、JavaScriptバックエンドの大規模改善演算子オーバーロードの設計改善ベアメタル/UEFIサポートインラインユニオン型 (int | null) の実装プラットフォームディレクティブの導入を含むリリースです。JSバックエンドのテスト通過率が55%から87%に向上し、演算子オーバーロードではimpl T構文と複合代入演算子(+=等)をサポートしました。また、UEFIターゲットでのベアメタル開発が可能になりました。

主要な変更点


🚀 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::Nullmake_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つの個別テストに分割し、問題の切り分けを可能にしました:

⚡ パフォーマンス改善

コンパイル速度の大幅改善

MIR最適化パイプラインとキャッシュデフォルトの見直しにより、コンパイル時間を大幅に削減しました。

項目 改善前 改善後 削減率
UEFIコンパイル 2764ms 646ms 76%削減
MIR最適化 593ms 389ms 34%削減

主な変更点:


🖥️ ベアメタル / 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.ymlextension-lint ジョブを追加。push/PRごとに以下を自動チェック:

  1. TypeScript compile
  2. ESLint check
  3. 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

📊 統計


🔮 今後の予定


📝 謝辞

このリリースは、JSバックエンドの品質大幅向上とNative/JS間の出力一致性確保という重要な目標を達成しました。また、UEFIコンパイル時間を2764msから646msに削減(76%改善)し、コンパイラのパフォーマンスも向上しました。