├── .gitignore ├── entrypoint.sh ├── Dockerfile ├── LICENSE ├── main.go └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.exe -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | wasm-opt "$@" 3 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | ADD entrypoint.sh /entrypoint.sh 3 | RUN mkdir wasm-opt && chmod +x /entrypoint.sh 4 | RUN wget -qO- https://github.com/WebAssembly/binaryen/releases/download/version_50/binaryen-version_50-x86_64-linux.tar.gz | tar xvz -C /wasm-opt binaryen-version_50/wasm-opt --strip=1 5 | ENV PATH $PATH:/wasm-opt 6 | ENTRYPOINT ["/entrypoint.sh"] 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 gonowa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "os" 7 | "os/exec" 8 | "path" 9 | "path/filepath" 10 | "strings" 11 | ) 12 | 13 | const ( 14 | containerOutDir = "/out" 15 | containerInDir = "/in" 16 | dockerImage = "gonowa/wasm-opt" 17 | ) 18 | 19 | func main() { 20 | 21 | mArgs, srcDir, dstDir := buildArgs(os.Args[1:]) 22 | 23 | var args = []string{"run", "--rm"} 24 | 25 | if srcDir != "" { 26 | args = append(args, "-v", strings.Join([]string{srcDir, containerInDir}, ":")) 27 | //most likely 28 | if srcDir == dstDir { 29 | args = append(args, "-v", strings.Join([]string{dstDir, containerOutDir}, ":")) 30 | } else { 31 | if dstDir != "" { 32 | args = append(args, "-v", strings.Join([]string{dstDir, containerOutDir}, ":")) 33 | } 34 | } 35 | } 36 | 37 | args = append(args, "-i", dockerImage) 38 | args = append(args, mArgs...) 39 | cmd := exec.Command("docker", args...) 40 | if Debug(args) { 41 | fmt.Fprintf(os.Stdout, "runing - %s\n", strings.Join(cmd.Args, " ")) 42 | } 43 | 44 | cmd.Stdout = os.Stdout 45 | cmd.Stderr = os.Stderr 46 | 47 | err := cmd.Run() 48 | if err != nil { 49 | os.Exit(1) 50 | } 51 | 52 | } 53 | 54 | func buildArgs(args []string) (mArgs []string, srcDir, dstDir string) { 55 | for i := 0; i < len(args); i++ { 56 | if isFlag(args[i]) { 57 | if isOutput(args[i]) { 58 | mArgs = append(mArgs, args[i]) 59 | //next arg is the output file 60 | //todo guard this 61 | if len(args) < i+1 { 62 | log.Fatalln("you must specify output file") 63 | } 64 | output := args[i+1] 65 | //get ouput path dir 66 | dstDir = filepath.Dir(AbsPath(output)) 67 | mArgs = append(mArgs, path.Join(containerOutDir, filepath.Base(args[i+1]))) 68 | i++ 69 | } else { 70 | mArgs = append(mArgs, args[i]) 71 | } 72 | } else { //input file 73 | srcDir = filepath.Dir(AbsPath(args[i])) 74 | mArgs = append(mArgs, path.Join(containerInDir, filepath.Base(args[i]))) 75 | } 76 | } 77 | return 78 | } 79 | 80 | func isFlag(str string) bool { 81 | if strings.HasPrefix(str, "-") { 82 | return true 83 | } 84 | return false 85 | } 86 | 87 | func AbsPath(str string) string { 88 | abspath, err := filepath.Abs(str) 89 | if err != nil { 90 | panic(err) 91 | } 92 | return abspath 93 | } 94 | 95 | func isOutput(str string) bool { 96 | if str == "-o" || str == "--output" { 97 | return true 98 | } 99 | return false 100 | } 101 | 102 | func Debug(args []string) bool { 103 | for i := range args { 104 | if args[i] == "-d" || args[i] == "--debug" { 105 | return true 106 | } 107 | } 108 | return false 109 | } 110 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wasm-opt 2 | wasm optimizer as docker container (7.96MB image) 3 | 4 | # motivation 5 | currently https://github.com/WebAssembly/binaryen doesn't provide windows binaries. 6 | this is a `cross platform`(kinda) version of wasm-opt. 7 | 8 | # requirements 9 | * docker 10 | * go 11 | 12 | # install 13 | ```sh 14 | go get -u github.com/gonowa/wasm-opt 15 | ``` 16 | 17 | # known issues 18 | bugs should be reported at https://github.com/WebAssembly/binaryen/issues, after all, this is just a thin wrapper arround wasm-opt 19 | * core dump or segmentation fault ( try to run with -d option) 20 | 21 | # usage 22 | 23 | ``` 24 | wasm-opt INFILE 25 | 26 | Read, write, and optimize files 27 | 28 | Options: 29 | --help,-h Show this help message and exit 30 | --debug,-d Print debug information to stderr 31 | -O execute default optimization 32 | passes 33 | -O0 execute no optimization passes 34 | -O1 execute -O1 optimization passes 35 | (quick&useful opts, useful for 36 | iteration builds) 37 | -O2 execute -O2 optimization passes 38 | (most opts, generally gets most 39 | perf) 40 | -O3 execute -O3 optimization passes 41 | (spends potentially a lot of time 42 | optimizing) 43 | -O4 execute -O4 optimization passes 44 | (also flatten the IR, which can 45 | take a lot more time and memory, 46 | but is useful on more nested / 47 | complex / less-optimized input) 48 | -Os execute default optimization 49 | passes, focusing on code size 50 | -Oz execute default optimization 51 | passes, super-focusing on code 52 | size 53 | --optimize-level,-ol How much to focus on optimizing 54 | code 55 | --shrink-level,-s How much to focus on shrinking 56 | code size 57 | --no-validation,-n Disables validation, assumes 58 | inputs are correct 59 | --ignore-implicit-traps,-iit Optimize under the helpful 60 | assumption that no surprising 61 | traps occur (from load, div/mod, 62 | etc.) 63 | --coalesce-locals reduce # of locals by coalescing 64 | --coalesce-locals-learning reduce # of locals by coalescing 65 | and learning 66 | --code-folding fold code, merging duplicates 67 | --code-pushing push code forward, potentially 68 | making it not always execute 69 | --const-hoisting hoist repeated constants to a 70 | local 71 | --dce removes unreachable code 72 | --duplicate-function-elimination removes duplicate functions 73 | --extract-function leaves just one function (useful 74 | for debugging) 75 | --flatten flattens out code, removing 76 | nesting 77 | --fpcast-emu emulates function pointer casts, 78 | allowing incorrect indirect calls 79 | to (sometimes) work 80 | --func-metrics reports function metrics 81 | --i64-to-i32-lowering lower all uses of i64s to use 82 | i32s instead 83 | --inlining inline functions (you probably 84 | want inlining-optimizing) 85 | --inlining-optimizing inline functions and optimizes 86 | where we inlined 87 | --instrument-locals instrument the build with code to 88 | intercept all loads and stores 89 | --instrument-memory instrument the build with code to 90 | intercept all loads and stores 91 | --legalize-js-interface legalizes i64 types on the 92 | import/export boundary 93 | --local-cse common subexpression elimination 94 | inside basic blocks 95 | --log-execution instrument the build with logging 96 | of where execution goes 97 | --memory-packing packs memory into separate 98 | segments, skipping zeros 99 | --merge-blocks merges blocks to their parents 100 | --merge-locals merges locals when beneficial 101 | --metrics reports metrics 102 | --nm name list 103 | --optimize-instructions optimizes instruction 104 | combinations 105 | --pick-load-signs pick load signs based on their 106 | uses 107 | --post-emscripten miscellaneous optimizations for 108 | Emscripten-generated code 109 | --precompute computes compile-time evaluatable 110 | expressions 111 | --precompute-propagate computes compile-time evaluatable 112 | expressions and propagates them 113 | through locals 114 | --print print in s-expression format 115 | --print-call-graph print call graph 116 | --print-full print in full s-expression format 117 | --print-minified print in minified s-expression 118 | format 119 | --relooper-jump-threading thread relooper jumps (fastcomp 120 | output only) 121 | --remove-imports removes imports and replaces them 122 | with nops 123 | --remove-memory removes memory segments 124 | --remove-non-js-ops removes operations incompatible 125 | with js 126 | --remove-unused-brs removes breaks from locations 127 | that are not needed 128 | --remove-unused-module-elements removes unused module elements 129 | --remove-unused-names removes names from locations that 130 | are never branched to 131 | --remove-unused-nonfunction-module-elements removes unused module elements 132 | that are not functions 133 | --reorder-functions sorts functions by access 134 | frequency 135 | --reorder-locals sorts locals by access frequency 136 | --rereloop re-optimize control flow using 137 | the relooper algorithm 138 | --rse remove redundant set_locals 139 | --safe-heap instrument loads and stores to 140 | check for invalid behavior 141 | --simplify-locals miscellaneous locals-related 142 | optimizations 143 | --simplify-locals-nonesting miscellaneous locals-related 144 | optimizations (no nesting at all; 145 | preserves flatness) 146 | --simplify-locals-nostructure miscellaneous locals-related 147 | optimizations 148 | --simplify-locals-notee miscellaneous locals-related 149 | optimizations 150 | --simplify-locals-notee-nostructure miscellaneous locals-related 151 | optimizations 152 | --spill-pointers spill pointers to the C stack 153 | (useful for Boehm-style GC) 154 | --ssa ssa-ify variables so that they 155 | have a single assignment 156 | --trap-mode-clamp replace trapping operations with 157 | clamping semantics 158 | --trap-mode-js replace trapping operations with 159 | js semantics 160 | --untee removes tee_locals, replacing 161 | them with sets and gets 162 | --vacuum removes obviously unneeded code 163 | --output,-o Output file (stdout if not 164 | specified) 165 | --emit-text,-S Emit text instead of binary for 166 | the output file 167 | --debuginfo,-g Emit names section and debug info 168 | --converge,-c Run passes to convergence, 169 | continuing while binary size 170 | decreases 171 | --fuzz-exec,-fe Execute functions before and 172 | after optimization, helping 173 | fuzzing find bugs 174 | --fuzz-binary,-fb Convert to binary and back after 175 | optimizations and before 176 | fuzz-exec, helping fuzzing find 177 | binary format bugs 178 | --extra-fuzz-command,-efc An extra command to run on the 179 | output before and after 180 | optimizing. The output is 181 | compared between the two, and an 182 | error occurs if they are not 183 | equal 184 | --translate-to-fuzz,-ttf Translate the input into a valid 185 | wasm module *somehow*, useful for 186 | fuzzing 187 | --fuzz-passes,-fp Pick a random set of passes to 188 | run, useful for fuzzing. this 189 | depends on translate-to-fuzz (it 190 | picks the passes from the input) 191 | --emit-js-wrapper,-ejw Emit a JavaScript wrapper file 192 | that can run the wasm with some 193 | test values, useful for fuzzing 194 | --emit-spec-wrapper,-esw Emit a wasm spec interpreter 195 | wrapper file that can run the 196 | wasm with some test values, 197 | useful for fuzzing 198 | --input-source-map,-ism Consume source map from the 199 | specified file 200 | --output-source-map,-osm Emit source map to the specified 201 | file 202 | --output-source-map-url,-osu Emit specified string as source 203 | map URL 204 | 205 | ``` 206 | 207 | --------------------------------------------------------------------------------