diff --git a/internal/app/appbase/flags.go b/internal/app/appbase/flags.go index 630632af..6092e3fe 100644 --- a/internal/app/appbase/flags.go +++ b/internal/app/appbase/flags.go @@ -8,6 +8,14 @@ import ( "wa-lang.org/wa/internal/config" ) +// wabt工具 +func MakeFlag_wabt() *cli.BoolFlag { + return &cli.BoolFlag{ + Name: "wabt", + Usage: "use wabt/wat2wasm tool", + } +} + // 输出路径 func MakeFlag_output() *cli.StringFlag { return &cli.StringFlag{ diff --git a/internal/app/appbase/opt.go b/internal/app/appbase/opt.go index 39d4e848..c7d8e1fb 100644 --- a/internal/app/appbase/opt.go +++ b/internal/app/appbase/opt.go @@ -13,6 +13,7 @@ import ( // 命令行选项 type Option struct { + UseWabt bool Debug bool WaBackend string BuilgTags []string @@ -80,6 +81,10 @@ func BuildOptions(c *cli.Context, waBackend ...string) *Option { LD_MaxMemory: c.Int("ld-max-memory"), } + if c.Bool("wabt") { + opt.UseWabt = true + } + opt.TargetArch = "wasm" if len(waBackend) > 0 { opt.WaBackend = waBackend[0] diff --git a/internal/app/appbuild/appbuild.go b/internal/app/appbuild/appbuild.go index 15938466..802cc3aa 100644 --- a/internal/app/appbuild/appbuild.go +++ b/internal/app/appbuild/appbuild.go @@ -13,12 +13,14 @@ import ( "wa-lang.org/wa/internal/config" "wa-lang.org/wa/internal/loader" "wa-lang.org/wa/internal/wabt" + "wa-lang.org/wa/internal/wat/watutil" ) var CmdBuild = &cli.Command{ Name: "build", Usage: "compile Wa source code", Flags: []cli.Flag{ + appbase.MakeFlag_wabt(), appbase.MakeFlag_output(), appbase.MakeFlag_target(), appbase.MakeFlag_tags(), @@ -75,7 +77,7 @@ func BuildApp(opt *appbase.Option, input, outfile string) (mainFunc string, wasm fmt.Printf("read %s failed: %v\n", input, err) os.Exit(1) } - wasmBytes, err := wabt.Wat2Wasm(watData) + wasmBytes, err := wat2wasm(opt.UseWabt, input, watData) if err != nil { fmt.Printf("wat2wasm %s failed: %v\n", input, err) os.Exit(1) @@ -114,7 +116,7 @@ func BuildApp(opt *appbase.Option, input, outfile string) (mainFunc string, wasm } // wat 编译为 wasm - wasmBytes, err := wabt.Wat2Wasm(watOutput) + wasmBytes, err := wat2wasm(opt.UseWabt, watOutfile, watOutput) if err != nil { fmt.Printf("wat2wasm %s failed: %v\n", input, err) os.Exit(1) @@ -196,7 +198,7 @@ func BuildApp(opt *appbase.Option, input, outfile string) (mainFunc string, wasm } // wat 编译为 wasm - wasmBytes, err := wabt.Wat2Wasm(watOutput) + wasmBytes, err := wat2wasm(opt.UseWabt, input, watOutput) if err != nil { fmt.Printf("wat2wasm %s failed: %v\n", input, err) os.Exit(1) @@ -217,6 +219,14 @@ func BuildApp(opt *appbase.Option, input, outfile string) (mainFunc string, wasm } } +func wat2wasm(useWabt bool, filename string, watBytes []byte) (wasmBytes []byte, err error) { + if useWabt { + return wabt.Wat2Wasm(watBytes) + } else { + return watutil.Wat2Wasm(filename, watBytes) + } +} + func buildWat(opt *appbase.Option, filename string) ( prog *loader.Program, compiler *compiler_wat.Compiler, watBytes []byte, err error, diff --git a/internal/app/apprun/apprun.go b/internal/app/apprun/apprun.go index ce1bd8f6..c2c54d44 100644 --- a/internal/app/apprun/apprun.go +++ b/internal/app/apprun/apprun.go @@ -25,6 +25,7 @@ var CmdRun = &cli.Command{ Name: "run", Usage: "compile and run Wa program", Flags: []cli.Flag{ + appbase.MakeFlag_wabt(), appbase.MakeFlag_target(), appbase.MakeFlag_tags(), &cli.BoolFlag{ diff --git a/internal/wabt/wat2wasm_test.go b/internal/wabt/wat2wasm_test.go index 6ac3ab8f..25bf188f 100644 --- a/internal/wabt/wat2wasm_test.go +++ b/internal/wabt/wat2wasm_test.go @@ -48,15 +48,6 @@ var watTests = []struct { watCode string errMsg string }{ - { - watCode: ``, - errMsg: `error: unexpected token "EOF", expected a module field or a module.`, - }, - { - watCode: `()`, - errMsg: `error: unexpected token ")", expected a module field or a module.`, - }, - { watCode: `(module)`, errMsg: "", @@ -70,43 +61,12 @@ var watTests = []struct { errMsg: "", }, - { - watCode: t_hello_wasi, - errMsg: "", - }, { watCode: tBuildWat(t_hello_wa), errMsg: "", }, } -const t_hello_wasi = ` -(module $hello_wasi - ;; type iov struct { iov_base, iov_len int32 } - ;; func fd_write(id *iov, iovs_len int32, nwritten *int32) (written int32) - (import "wasi_unstable" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32))) - - (memory 1)(export "memory" (memory 0)) - - ;; 前 8 个字节保留给 iov 数组, 字符串从地址 8 开始 - (data (i32.const 8) "hello world\n") - - ;; _start 类似 main 函数, 自动执行 - (func $main (export "_start") - (i32.store (i32.const 0) (i32.const 8)) ;; iov.iov_base - 字符串地址为 8 - (i32.store (i32.const 4) (i32.const 12)) ;; iov.iov_len - 字符串长度 - - (call $fd_write - (i32.const 1) ;; 1 对应 stdout - (i32.const 0) ;; *iovs - 前 8 个字节保留给 iov 数组 - (i32.const 1) ;; len(iovs) - 只有1个字符串 - (i32.const 20) ;; nwritten - 指针, 里面是要写到数据长度 - ) - drop ;; 忽略返回值 - ) -) -` - const t_hello_wa = ` // 版权 @2019 凹语言 作者。保留所有权利。 diff --git a/internal/wat/parser/module_func_instruction.go b/internal/wat/parser/module_func_instruction.go index b47489f9..ed0950f0 100644 --- a/internal/wat/parser/module_func_instruction.go +++ b/internal/wat/parser/module_func_instruction.go @@ -719,7 +719,7 @@ func (p *parser) parseIns_I32Load16S() (i ast.Ins_I32Load16S) { } func (p *parser) parseIns_I32Load16U() (i ast.Ins_I32Load16U) { i.OpToken = ast.OpToken(p.tok) - p.acceptToken(token.INS_I32_LOAD16_S) + p.acceptToken(token.INS_I32_LOAD16_U) if p.tok == token.OFFSET { p.acceptToken(token.OFFSET) p.acceptToken(token.ASSIGN) diff --git a/internal/wat/parser/parser.go b/internal/wat/parser/parser.go index 3776299a..1da61ccb 100644 --- a/internal/wat/parser/parser.go +++ b/internal/wat/parser/parser.go @@ -170,11 +170,16 @@ func (p *parser) parseInt32Lit() int32 { p.acceptToken(token.INT) // 需要支持 u32 和 -1 两种格式 - n, err := strconv.ParseInt(lit, 10, 33) + n, err := strconv.ParseInt(lit, 10, 32) if err != nil { - p.errorf(pos, "expect int, got %q, err = %v", lit, err) + if n, errx := strconv.ParseUint(lit, 10, 32); errx == nil { + return int32(uint32(n)) + } else { + p.errorf(pos, "expect int, got %q, err = %v", lit, err) + } + } - return int32(uint32(n)) + return int32(n) } func (p *parser) parseUint32Lit() uint32 { pos, lit := p.pos, p.lit @@ -190,7 +195,7 @@ func (p *parser) parseInt64Lit() int64 { pos, lit := p.pos, p.lit p.acceptToken(token.INT) - n, err := strconv.ParseUint(lit, 10, 64) + n, err := strconv.ParseInt(lit, 10, 64) if err != nil { p.errorf(pos, "expect int, got %q", lit) } diff --git a/waroot/src/src.go b/waroot/src/src.go index 1ed81704..7ba76948 100644 --- a/waroot/src/src.go +++ b/waroot/src/src.go @@ -100,7 +100,7 @@ var stdPkgs = []string{ "apple", // 测试已覆盖, wat2wasm ok "archive/txtar", // API 完整, wat2wasm ok "bufio", // API 完整, wat2wasm ok - "bytes", // API 完整, wat2wasm failed + "bytes", // API 完整, wat2wasm ok "compress/snappy", // ? "container/heap", // ? "container/list", // ? @@ -108,11 +108,11 @@ var stdPkgs = []string{ "crypto/md5", // ?, 测试失败, Skip, wat2wasm ok "errors", // API 完整, 测试已覆盖, wat2wasm ok "encoding", // API 完整, wat2wasm ok - "encoding/base32", // ?, wat2wasm failed - "encoding/base64", // API 完整, wat2wasm failed - "encoding/binary", // API 部分, wat2wasm failed + "encoding/base32", // ?, wat2wasm ok + "encoding/base64", // API 完整, wat2wasm ok + "encoding/binary", // API 部分, wat2wasm ok "encoding/hex", // API 完整, wat2wasm ok - "encoding/pem", // ?, wat2wasm failed + "encoding/pem", // ?, wat2wasm ok "encoding/qrcode", // ? "debug", // ? "fmt", // ?, wat2wasm ok @@ -128,18 +128,18 @@ var stdPkgs = []string{ "js/canvas", // ? "js/p5", // ? "math", // API 部分 - "math/big", // API 部分, wat2wasm failed - "math/bits", // API 完整, wat2wasm failed - "math/gf256", // ?, wat2wasm failed + "math/big", // API 部分, wat2wasm ok + "math/bits", // API 完整, wat2wasm ok + "math/gf256", // ?, wat2wasm ok "net", // ? "os", // API 部分, wat2wasm ok - "reflect", // ?, wat2wasm failed + "reflect", // ? "regexp", // API 部分 "runtime", // - "sort", // API 完整, wat2wasm failed - "strconv", // API 完整, wat2wasm failed + "sort", // API 完整, wat2wasm ok + "strconv", // API 完整, wat2wasm ok "strings", // API 完整, wat2wasm ok - "syscall", // API 完整, wat2wasm failed + "syscall", // API 完整 "syscall/js", // "syscall/wasi", // "syscall/unknown", //