├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── add
├── Makefile
├── README.md
├── index.html
├── main.c
└── main.wasm
├── animation
├── Makefile
├── README.md
├── index.html
├── main.c
└── main.wasm
├── importexport
├── Makefile
├── README.md
├── index.html
├── main.c
└── main.wasm
├── index.html
├── malloc
├── Makefile
├── README.md
├── index.html
├── main.c
└── main.wasm
├── memory
├── Makefile
├── README.md
├── index.html
├── main.c
└── main.wasm
├── pong
├── Makefile
├── README.md
├── index.html
├── main.c
└── main.wasm
├── strings
├── Makefile
├── README.md
├── index.html
├── main.c
└── main.wasm
├── tools
└── Makefile
├── wat
├── Makefile
├── add.wasm
├── add.wat
├── fibonacci.wasm
├── fibonacci.wat
├── index.html
├── print.wasm
└── print.wat
└── webgl
├── Makefile
├── README.md
├── index.html
├── main.c
└── main.wasm
/.gitignore:
--------------------------------------------------------------------------------
1 | tools/bin
2 | tools/build
3 | tools/src
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017
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 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | TOOLS=$(dir $(lastword $(MAKEFILE_LIST)))/tools
2 | CLANG=$(TOOLS)/bin/bin/clang
3 | LLC=$(TOOLS)/bin/bin/llc
4 | S2WASM=$(TOOLS)/bin/s2wasm
5 | WAST2WASM=$(TOOLS)/bin/bin/wast2wasm
6 |
7 | %.bc : %.c
8 | ${CLANG} --target=wasm32 -Oz -c -emit-llvm $< -o $@
9 |
10 | %.s : %.bc
11 | ${LLC} $< -o $@
12 |
13 | %.wat : %.s
14 | ${S2WASM} $< > $@
15 |
16 | %.wasm : %.wat
17 | ${WAST2WASM} $< -o $@
18 |
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WASM-Intro
2 |
3 | A scratchpad of stuff in WebAssembly. All examples are written for simplicity, not good code style nor performance. Please do not use anything here in important stuff.
4 |
5 | Much of the toolchain is based on [yurydelendik's "Using WebAssembly in LLVM" gist](https://gist.github.com/yurydelendik/4eeff8248aeb14ce763e).
6 |
7 | ## Build environment
8 |
9 | Run `make build` and `make install` in `tools`. This builds LLVM, clang, binaryen and WABT with correct stuff for WebAssembly compiling.
10 |
11 | ## Examples
12 |
13 | Build by running `make` in each directory. Test using python3 by running `make serve` and browsing to localhost:8000.
14 |
15 | To build intermediate results from the C -> WASM compilation, try `make main.s` and `make main.wat`
16 |
17 | ### Add
18 |
19 | Simple function export example. Adds two numbers together and prints to console
20 |
21 | ### Import/Export
22 |
23 | Same as Add, now with an added step of delegating the addition back to JavaScript.
24 |
25 | ### Memory
26 |
27 | Poking an exported linear memory from JS and C.
28 |
29 | ### Strings
30 |
31 | Manipulating JS strings in C.
32 |
33 | ### Malloc
34 |
35 | Implementing a simple toy dynamic memory allocation scheme.
36 |
37 | ### Animation
38 |
39 | Some canvas functions imported to WASM, shows bouncing particles.
40 |
41 | ### WebGL
42 |
43 | Wraps a portion of WebGL API for importing to WASM, draws a moving triangle.
44 |
45 | ### Pong
46 |
47 | Wraps a little more of WebGL API for importing to WASM, plays Pong.
48 |
--------------------------------------------------------------------------------
/add/Makefile:
--------------------------------------------------------------------------------
1 | include ../Makefile
2 |
3 | all: main.wasm
4 |
5 | serve:
6 | python3 -m http.server
7 |
--------------------------------------------------------------------------------
/add/README.md:
--------------------------------------------------------------------------------
1 | # wasm-intro/add
2 |
3 | A trivial example of:
4 |
5 | - Defining a WASM function in C
6 | - Loading a WASM module and calling a WASM function from JavaScript
7 |
8 | The page loads the WASM module and calls it to add two integers together.
9 |
--------------------------------------------------------------------------------
/add/index.html:
--------------------------------------------------------------------------------
1 |
18 |
--------------------------------------------------------------------------------
/add/main.c:
--------------------------------------------------------------------------------
1 | int add(int a, int b) {
2 | return a + b;
3 | }
4 |
--------------------------------------------------------------------------------
/add/main.wasm:
--------------------------------------------------------------------------------
1 | asm ` p memory add
2 | j
--------------------------------------------------------------------------------
/animation/Makefile:
--------------------------------------------------------------------------------
1 | include ../Makefile
2 |
3 | all: main.wasm
4 |
5 | serve:
6 | python3 -m http.server
7 |
--------------------------------------------------------------------------------
/animation/README.md:
--------------------------------------------------------------------------------
1 | # wasm-intro/animation
2 |
3 | A trivial example of:
4 |
5 | - Defining a WASM function in C
6 | - Wrapping Web APIs for calling from WASM
7 | - Animation through onAnimationFrame -> WASM -> Canvas API
8 | - Loading a WASM module, providing external functions and calling a WASM function from JavaScript and vice versa
9 |
10 | The page loads the WASM module and calls it each animation frame to draw bouncing particles on a canvas.
11 |
12 |
--------------------------------------------------------------------------------
/animation/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/animation/main.c:
--------------------------------------------------------------------------------
1 | extern void setFillColor(int, int, int, int);
2 | extern void fillRect(int, int, int, int);
3 | extern int getCanvasWidth();
4 | extern int getCanvasHeight();
5 |
6 | typedef struct {
7 | float x;
8 | float y;
9 | float vx;
10 | float vy;
11 | } Particle;
12 |
13 | Particle particles[100];
14 | int width;
15 | int height;
16 |
17 | void bounce(float* position, float* velocity, float minValue, float maxValue) {
18 | if (*position > maxValue) {
19 | *position -= *position - maxValue;
20 | *velocity = -*velocity;
21 | } else if (*position < minValue) {
22 | *position = minValue + (minValue - *position);
23 | *velocity = -*velocity;
24 | }
25 | }
26 |
27 | void onInit() {
28 | width = getCanvasWidth();
29 | height = getCanvasHeight();
30 | for (int i = 0; i < 100; ++i) {
31 | particles[i].x = width/2.0;
32 | particles[i].y = height/2.0;
33 | particles[i].vx = ((i*7 % 200) - 100)/100.0;
34 | particles[i].vy = ((i*19 % 200) - 100)/100.0;
35 | }
36 | }
37 |
38 | void onAnimationFrame(int timestamp) {
39 | static int previous = 0;
40 |
41 | int delta = previous ? timestamp - previous : 0;
42 |
43 | setFillColor(64,64,64,255);
44 | fillRect(0, 0, width, height);
45 |
46 | setFillColor(255,0,0,255);
47 | for (int i = 0; i < 100; ++i) {
48 | particles[i].vy += 0.001 * delta;
49 | particles[i].x += particles[i].vx * delta;
50 | particles[i].y += particles[i].vy * delta;
51 |
52 | bounce(&particles[i].x, &particles[i].vx, 0, width - 10);
53 | bounce(&particles[i].y, &particles[i].vy, 0, height - 10);
54 |
55 | fillRect((int) (particles[i].x + 0.5), (int) (particles[i].y + 0.5), 10, 10);
56 | }
57 |
58 | previous = timestamp;
59 | }
60 |
--------------------------------------------------------------------------------
/animation/main.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bzar/wasm-intro/d53c653b35649f9433ef5e7f5fff9da49483221b/animation/main.wasm
--------------------------------------------------------------------------------
/importexport/Makefile:
--------------------------------------------------------------------------------
1 | include ../Makefile
2 |
3 | all: main.wasm
4 |
5 | serve:
6 | python3 -m http.server
7 |
--------------------------------------------------------------------------------
/importexport/README.md:
--------------------------------------------------------------------------------
1 | # wasm-intro/importexport
2 |
3 | A trivial example of:
4 |
5 | - Defining a WASM function in C
6 | - Defining an external function callable from C
7 | - Loading a WASM module, providing external functions and calling a WASM function from JavaScript
8 |
9 | The page loads the WASM module and calls it to call a JavaScript function to add two integers together.
10 |
--------------------------------------------------------------------------------
/importexport/index.html:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/importexport/main.c:
--------------------------------------------------------------------------------
1 | extern int js_add(int, int);
2 |
3 |
4 | int add(int a, int b) {
5 | return js_add(a, b);
6 | }
7 |
--------------------------------------------------------------------------------
/importexport/main.wasm:
--------------------------------------------------------------------------------
1 | asm `envjs_add p memory add
2 |
3 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/malloc/Makefile:
--------------------------------------------------------------------------------
1 | include ../Makefile
2 |
3 | all: main.wasm
4 |
5 | serve:
6 | python3 -m http.server
7 |
--------------------------------------------------------------------------------
/malloc/README.md:
--------------------------------------------------------------------------------
1 | # wasm-intro/malloc
2 |
3 | A trivial example of:
4 |
5 | - Defining a WASM function in C
6 | - Accessing WASM linear memory from both JavaScript and C
7 | - Implementing a simple toy malloc/free/sizeof toolchain to manage dynamic memory allocation
8 | - Loading a WASM module and calling a WASM function from JavaScript
9 |
10 | The page loads the WASM module, then allocates WASM linear memory using a custom malloc implementation to store strings, which are then read and printed with the help of msize. Next the middle one is freed using mfree, and its memory block is reused for another smaller string allocation.
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/malloc/index.html:
--------------------------------------------------------------------------------
1 |
65 |
--------------------------------------------------------------------------------
/malloc/main.c:
--------------------------------------------------------------------------------
1 | typedef struct Block {
2 | unsigned int size;
3 | unsigned int usize;
4 | struct Block* next;
5 | struct Block* prev;
6 | } Block;
7 |
8 | Block* usedBlocks = 0;
9 | Block* freeBlocks = 0;
10 | Block* nextBlock = (Block*) 1024;
11 |
12 | void* malloc(unsigned int size) {
13 | Block* b = freeBlocks;
14 | while (b && b->size < size) b = b->next;
15 |
16 | if(!b) {
17 | b = nextBlock;
18 | b->size = size;
19 | nextBlock += size + sizeof(Block); // Header + data
20 | }
21 |
22 | b->usize = size;
23 | b->next = usedBlocks;
24 | if(b->next) b->next->prev = b;
25 | b->prev = 0;
26 | usedBlocks = b;
27 |
28 | return (void*) b + sizeof(Block);
29 | }
30 |
31 | void mfree(void* data) {
32 | Block* b = data - sizeof(Block);
33 | if(b->prev) b->prev->next = b->next;
34 | b->next = freeBlocks;
35 | if(b->next) b->next->prev = b;
36 | b->prev = 0;
37 | freeBlocks = b;
38 | }
39 |
40 | unsigned int msize(void* data) {
41 | Block* b = data - sizeof(Block);
42 | return b->usize;
43 | }
44 |
--------------------------------------------------------------------------------
/malloc/main.wasm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bzar/wasm-intro/d53c653b35649f9433ef5e7f5fff9da49483221b/malloc/main.wasm
--------------------------------------------------------------------------------
/memory/Makefile:
--------------------------------------------------------------------------------
1 | include ../Makefile
2 |
3 | all: main.wasm
4 |
5 | serve:
6 | python3 -m http.server
7 |
--------------------------------------------------------------------------------
/memory/README.md:
--------------------------------------------------------------------------------
1 | # wasm-intro/memory
2 |
3 | A trivial example of:
4 |
5 | - Defining a WASM function in C
6 | - Defining external functions callable from C
7 | - Accessing WASM linear memory from both JavaScript and C
8 | - Loading a WASM module and calling a WASM function from JavaScript
9 |
10 | The page loads the WASM module, then manipulates and reads its exported memory using both JavaScript typed arrays and C pointers.
11 |
12 |
--------------------------------------------------------------------------------
/memory/index.html:
--------------------------------------------------------------------------------
1 |
31 |
--------------------------------------------------------------------------------
/memory/main.c:
--------------------------------------------------------------------------------
1 | unsigned int* memory = 0;
2 |
3 | unsigned int put(unsigned int offset, unsigned int value) {
4 | *(memory + offset) = value;
5 | return *(memory + offset);
6 | }
7 |
8 | unsigned int get(unsigned int offset) {
9 | return *(memory + offset);
10 | }
11 |
--------------------------------------------------------------------------------
/memory/main.wasm:
--------------------------------------------------------------------------------
1 | asm `` p memory put get
2 | ' A ( Atj 6 A ( Atj(
3 | A
--------------------------------------------------------------------------------
/pong/Makefile:
--------------------------------------------------------------------------------
1 | include ../Makefile
2 |
3 | all: main.wasm
4 |
5 | serve:
6 | python3 -m http.server
7 |
--------------------------------------------------------------------------------
/pong/README.md:
--------------------------------------------------------------------------------
1 | # wasm-intro/pong
2 |
3 | A non-trivial example of:
4 |
5 | - Defining a WASM function in C
6 | - Wrapping WebGL API for calling from WASM
7 | - Wrapping Web Audio API for calling from WASM
8 | - Animation through onAnimationFrame -> WASM -> Canvas API
9 | - Loading a WASM module, providing external functions and calling a WASM function from JavaScript and vice versa
10 |
11 | The page loads the WASM module and calls it each animation frame and input event to play pong on a canvas using WebGL. The game also generates sound effects in WASM to play through an AudioBuffer.
12 |
13 |
--------------------------------------------------------------------------------
/pong/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |