feat: Apply Copilot's WASM UTF-8 fix manually
- Change from compile_module() to compile_to_wat() to fix UTF-8 error - WASM compilation now outputs WAT text format directly - Successfully generates WAT file for simple test case - Note: Debug build still has issues (separate bug) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -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%達成!**
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
local result = 42
|
||||
local result = 42
|
||||
218
local_tests/test_simple_wasm.wat
Normal file
218
local_tests/test_simple_wasm.wat
Normal file
@ -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))
|
||||
)
|
||||
@ -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(()) => {
|
||||
|
||||
Reference in New Issue
Block a user