diff --git a/docs/CURRENT_TASK.md b/docs/CURRENT_TASK.md index f3013a50..99c4b48a 100644 --- a/docs/CURRENT_TASK.md +++ b/docs/CURRENT_TASK.md @@ -1,6 +1,6 @@ # 🎯 現在のタスク (2025-08-16 Phase 9.77 WASM緊急復旧開始!) -## 🚨 **Phase 9.77進行中: WASM緊急復旧作業** +## ✅ **Phase 9.77完了: WASM緊急復旧作業完了!** ### ✅ **Task 1.1完了: BoxCall命令実装** - **BoxCall実装**: toString(), print(), equals(), clone(), log()メソッド完全実装 ✅ @@ -13,44 +13,38 @@ - **RuntimeImports追加**: box_to_string, box_print, box_equals, box_clone 実装済み ✅ - **ビルド成功**: バージョン互換性問題解決 ✅ -### 🔄 **Task 1.3進行中: WASM出力UTF-8エラー修正** -**現状**: 「Generated WASM is not valid UTF-8」エラーが継続 -```bash -❌ Generated WASM is not valid UTF-8 +### ✅ **Task 1.3完了: WASM出力UTF-8エラー修正(Copilot解決!)** +**問題**: 「Generated WASM is not valid UTF-8」エラー +**原因**: WASMバイナリをUTF-8文字列として扱っていた + +**Copilotの修正**: +```rust +// Before (broken) +let wasm_code = wasm_backend.compile_module(compile_result.module)?; +let output_str = std::str::from_utf8(&wasm_code)?; + +// After (fixed) +let wat_text = wasm_backend.compile_to_wat(compile_result.module)?; +let output_str = wat_text; ``` -**実装済み修正**: -- wabt::wat2wasm呼び出し修正(wat_source.as_bytes()使用) -- UTF-8検証とデバッグ出力追加 -- しかしエラーメッセージの発生元が不明 +**結果**: WAT(テキスト形式)を直接出力することで解決 ✅ -**調査結果**: -- エラーメッセージがソースコード内に見つからない -- wabt crateまたは外部ツールから発生している可能性 -- 簡単なテストケース(`local result = 42`)でも同じエラー +### 🎉 **Phase 9.77成果まとめ** +- ✅ BoxCall命令完全実装 +- ✅ wasmtime 35.0.0対応 +- ✅ UTF-8エラー解決(手動でCopilot修正を適用) +- ✅ WASM基本機能復旧(リリースビルドで動作確認) +- ✅ WATファイル生成成功: `local result = 42` → 正常なWAT出力 -### 📋 **Phase 9.77緊急復旧計画** -詳細: [phase_9_77_wasm_emergency.md](docs/予定/native-plan/issues/phase_9_77_wasm_emergency.md) +### 📋 **残課題** +- ⚠️ デバッグビルドでのWASMエラー(別のバグの可能性) +- 🔄 git pullでのマージコンフリクト(expressions.rsモジュール分割と衝突) -**Task 1.1**: ✅ BoxCall命令実装(完了) -**Task 1.2**: ✅ wasmtimeバージョン統一 + RuntimeImports(完了) -**Task 1.3**: 🔄 WASM出力エラー修正(進行中) - -### 🎯 **Copilotへの引き継ぎ事項** -1. **UTF-8エラーの原因特定** - - エラーメッセージ「Generated WASM is not valid UTF-8」の発生元調査 - - wabt::wat2wasm以外の場所でエラーが出ている可能性 - - runner.rsやmain.rsでのエラー処理確認 - -2. **デバッグアプローチ** - - WAT生成内容の詳細確認(デバッグ出力は実装済み) - - WASM生成パイプライン全体の調査 - - 最小再現テストケースでの検証 - -3. **修正候補** - - エラーメッセージの発生元を特定してから対応 - - WAT形式の検証強化 - - バイナリ出力処理の見直し +### 🚀 **次のステップ** +1. **デバッグビルドエラー調査**: なぜデバッグビルドで失敗するか +2. **WASM実行テスト**: 生成されたWATファイルの実行確認 +3. **Phase 10準備**: LLVM Direct AOT実装へ ## 🎉 **Phase 9.75j完了: 警告削減100%達成!** diff --git a/local_tests/test_simple_wasm.nyash b/local_tests/test_simple_wasm.nyash index da18925c..3c35cc59 100644 --- a/local_tests/test_simple_wasm.nyash +++ b/local_tests/test_simple_wasm.nyash @@ -1 +1 @@ -local result = 42 +local result = 42 \ No newline at end of file diff --git a/local_tests/test_simple_wasm.wat b/local_tests/test_simple_wasm.wat new file mode 100644 index 00000000..681f290d --- /dev/null +++ b/local_tests/test_simple_wasm.wat @@ -0,0 +1,218 @@ +(module + (import "env" "print" (func $print (param i32) )) + (import "env" "print_str" (func $print_str (param i32 i32) )) + (import "env" "console_log" (func $console_log (param i32 i32) )) + (import "env" "canvas_fillRect" (func $canvas_fillRect (param i32 i32 i32 i32 i32 i32 i32 i32) )) + (import "env" "canvas_fillText" (func $canvas_fillText (param i32 i32 i32 i32 i32 i32 i32 i32 i32 i32) )) + (import "env" "box_to_string" (func $box_to_string (param i32) (result i32))) + (import "env" "box_print" (func $box_print (param i32) )) + (import "env" "box_equals" (func $box_equals (param i32 i32) (result i32))) + (import "env" "box_clone" (func $box_clone (param i32) (result i32))) + (memory (export "memory") 1) + (data (i32.const 4096) "\49\6e\74\65\67\65\72\42\6f\78") + (global $heap_ptr (mut i32) (i32.const 2048)) + (func $malloc (param $size i32) (result i32) + (local $ptr i32) + (local $aligned_size i32) + + ;; Align size to 4-byte boundary + local.get $size + i32.const 3 + i32.add + i32.const -4 + i32.and + local.set $aligned_size + + ;; Get current heap pointer + global.get $heap_ptr + local.set $ptr + + ;; Advance heap pointer by aligned size + global.get $heap_ptr + local.get $aligned_size + i32.add + global.set $heap_ptr + + ;; Return allocated pointer + local.get $ptr + ) + (func $box_alloc (param $type_id i32) (param $field_count i32) (result i32) + (local $ptr i32) + (local $total_size i32) + + ;; Calculate total size: header (12) + fields (field_count * 4) + local.get $field_count + i32.const 4 + i32.mul + i32.const 12 + i32.add + local.set $total_size + + ;; Allocate memory + local.get $total_size + call $malloc + local.set $ptr + + ;; Initialize type_id + local.get $ptr + local.get $type_id + i32.store + + ;; Initialize ref_count to 1 + local.get $ptr + i32.const 4 + i32.add + i32.const 1 + i32.store + + ;; Initialize field_count + local.get $ptr + i32.const 8 + i32.add + local.get $field_count + i32.store + + ;; Return box pointer + local.get $ptr + ) + (func $alloc_stringbox (result i32) + (local $ptr i32) + + ;; Allocate memory for box + i32.const 20 + call $malloc + local.set $ptr + + ;; Initialize type_id + local.get $ptr + i32.const 4097 + i32.store + + ;; Initialize ref_count to 1 + local.get $ptr + i32.const 4 + i32.add + i32.const 1 + i32.store + + ;; Initialize field_count + local.get $ptr + i32.const 8 + i32.add + i32.const 2 + i32.store + + ;; Return box pointer + local.get $ptr + ) + (func $alloc_integerbox (result i32) + (local $ptr i32) + + ;; Allocate memory for box + i32.const 16 + call $malloc + local.set $ptr + + ;; Initialize type_id + local.get $ptr + i32.const 4098 + i32.store + + ;; Initialize ref_count to 1 + local.get $ptr + i32.const 4 + i32.add + i32.const 1 + i32.store + + ;; Initialize field_count + local.get $ptr + i32.const 8 + i32.add + i32.const 1 + i32.store + + ;; Return box pointer + local.get $ptr + ) + (func $alloc_boolbox (result i32) + (local $ptr i32) + + ;; Allocate memory for box + i32.const 16 + call $malloc + local.set $ptr + + ;; Initialize type_id + local.get $ptr + i32.const 4099 + i32.store + + ;; Initialize ref_count to 1 + local.get $ptr + i32.const 4 + i32.add + i32.const 1 + i32.store + + ;; Initialize field_count + local.get $ptr + i32.const 8 + i32.add + i32.const 1 + i32.store + + ;; Return box pointer + local.get $ptr + ) + (func $alloc_databox (result i32) + (local $ptr i32) + + ;; Allocate memory for box + i32.const 16 + call $malloc + local.set $ptr + + ;; Initialize type_id + local.get $ptr + i32.const 4101 + i32.store + + ;; Initialize ref_count to 1 + local.get $ptr + i32.const 4 + i32.add + i32.const 1 + i32.store + + ;; Initialize field_count + local.get $ptr + i32.const 8 + i32.add + i32.const 1 + i32.store + + ;; Return box pointer + local.get $ptr + ) + (func $main (local $0 i32) (local $1 i32) + nop + call $alloc_stringbox + local.set $1 + local.get $1 + i32.const 12 + i32.add + i32.const 4096 + i32.store + local.get $1 + i32.const 16 + i32.add + i32.const 10 + i32.store + local.get $1 + local.set $0 + local.get $0 + return + ) + (export "main" (func $main)) +) diff --git a/src/runner.rs b/src/runner.rs index 3b211dd7..45bff514 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -300,10 +300,10 @@ impl NyashRunner { } }; - // Compile to WASM + // Compile to WASM (Phase 9.77a fix: use compile_to_wat instead of compile_module) let mut wasm_backend = WasmBackend::new(); - let wasm_code = match wasm_backend.compile_module(compile_result.module) { - Ok(wasm) => wasm, + let wat_text = match wasm_backend.compile_to_wat(compile_result.module) { + Ok(wat) => wat, Err(e) => { eprintln!("❌ WASM compilation error: {}", e); process::exit(1); @@ -321,14 +321,8 @@ impl NyashRunner { }); let output_file = format!("{}.wat", output); - // Write WASM output - let output_str = match std::str::from_utf8(&wasm_code) { - Ok(s) => s, - Err(_) => { - eprintln!("❌ Generated WASM is not valid UTF-8"); - process::exit(1); - } - }; + // Write WAT output (already a string) + let output_str = wat_text; match fs::write(&output_file, output_str) { Ok(()) => {