@gasm-compiler/core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +17 -0
- package/README.md +720 -0
- package/dist/browser-executor.d.ts +76 -0
- package/dist/browser-executor.js +1 -0
- package/dist/browser.d.ts +20 -0
- package/dist/browser.js +1 -0
- package/dist/chunk-BRCWMQF4.js +5 -0
- package/dist/chunk-G6YRZSKB.js +1 -0
- package/dist/chunk-LC4DBTKT.js +5 -0
- package/dist/chunk-STDXBN5E.js +1 -0
- package/dist/compiler.d.ts +45 -0
- package/dist/compiler.js +1 -0
- package/dist/executor.d.ts +75 -0
- package/dist/executor.js +1 -0
- package/dist/mod.d.ts +91 -0
- package/dist/mod.js +1 -0
- package/dist/parser-Q0YamOJY.d.ts +390 -0
- package/package.json +72 -0
package/README.md
ADDED
|
@@ -0,0 +1,720 @@
|
|
|
1
|
+
# Gasm Compiler Core Compiler
|
|
2
|
+
|
|
3
|
+
**Compile WebAssembly to WGSL for GPU Execution**
|
|
4
|
+
|
|
5
|
+
This package implements the core compiler that transforms WebAssembly binaries into WGSL (WebGPU Shading Language) code for execution on GPUs. It implements the [Gasm v0.1 specification](../../spec/gasm-v0.1.md), a GPU-executable subset of WebAssembly.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Table of Contents
|
|
10
|
+
|
|
11
|
+
- [Overview](#overview)
|
|
12
|
+
- [Architecture](#architecture)
|
|
13
|
+
- [Compilation Pipeline](#compilation-pipeline)
|
|
14
|
+
- [IR Types](#ir-types)
|
|
15
|
+
- [Instruction Mapping](#instruction-mapping)
|
|
16
|
+
- [Gasm Conformance](#gasm-conformance)
|
|
17
|
+
- [Usage](#usage)
|
|
18
|
+
- [Testing](#testing)
|
|
19
|
+
- [API Reference](#api-reference)
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Overview
|
|
24
|
+
|
|
25
|
+
**Gasm Compiler Core** is a TypeScript/Deno compiler that:
|
|
26
|
+
|
|
27
|
+
1. **Parses** WebAssembly binaries (Wasm Core 1.0)
|
|
28
|
+
2. **Validates** GPU execution constraints (Gasm spec)
|
|
29
|
+
3. **Transforms** stack-based Wasm to structured WGSL
|
|
30
|
+
4. **Generates** WGSL compute shaders ready for WebGPU
|
|
31
|
+
|
|
32
|
+
### Key Features
|
|
33
|
+
|
|
34
|
+
- ✅ Full L0 conformance (scalar operations)
|
|
35
|
+
- ✅ 120+ WebAssembly instructions supported
|
|
36
|
+
- ✅ Control flow restructuring (Relooper algorithm)
|
|
37
|
+
- ✅ Memory operation lowering (sub-word access)
|
|
38
|
+
- ✅ Global imports and Gasm built-ins
|
|
39
|
+
- ✅ Type-safe SSA intermediate representation
|
|
40
|
+
- 🚧 L1/L2 conformance (SIMD, atomics) — planned
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Architecture
|
|
45
|
+
|
|
46
|
+
The compiler uses a **5-phase pipeline** to transform WebAssembly into WGSL:
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
┌─────────────┐
|
|
50
|
+
│ Wasm Binary │ Input: .wasm file (Uint8Array)
|
|
51
|
+
└──────┬──────┘
|
|
52
|
+
│
|
|
53
|
+
v
|
|
54
|
+
┌─────────────┐
|
|
55
|
+
│ Phase 1: │ Parse & Validate
|
|
56
|
+
│ Parser │ • Binary format parsing
|
|
57
|
+
│ │ • Gasm restriction validation (Section 10)
|
|
58
|
+
└──────┬──────┘ • Output: WasmModule (stack-based IR)
|
|
59
|
+
│
|
|
60
|
+
v
|
|
61
|
+
┌─────────────┐
|
|
62
|
+
│ Phase 2: │ Stack → SSA Conversion
|
|
63
|
+
│ SSA IR │ • Convert stack operations to SSA form
|
|
64
|
+
│ │ • Type inference for locals
|
|
65
|
+
└──────┬──────┘ • Output: SSAModule (SSA IR)
|
|
66
|
+
│
|
|
67
|
+
v
|
|
68
|
+
┌─────────────┐
|
|
69
|
+
│ Phase 3: │ Control Flow Restructuring
|
|
70
|
+
│ Relooper │ • Transform unstructured jumps (br, br_if, br_table)
|
|
71
|
+
│ │ • Generate structured blocks/loops
|
|
72
|
+
└──────┬──────┘ • Output: StructuredModule
|
|
73
|
+
│
|
|
74
|
+
v
|
|
75
|
+
┌─────────────┐
|
|
76
|
+
│ Phase 4: │ Memory Lowering
|
|
77
|
+
│ MemLower │ • Lower i8/i16 loads/stores to i32 word access
|
|
78
|
+
│ │ • Generate bit-masking and shifting
|
|
79
|
+
└──────┬──────┘ • Output: StructuredModule (memory-lowered)
|
|
80
|
+
│
|
|
81
|
+
v
|
|
82
|
+
┌─────────────┐
|
|
83
|
+
│ Phase 5: │ WGSL Code Generation
|
|
84
|
+
│ Codegen │ • Emit WGSL functions, variables, structs
|
|
85
|
+
│ │ • Map Wasm instructions to WGSL expressions
|
|
86
|
+
└──────┬──────┘ • Output: WGSL string
|
|
87
|
+
│
|
|
88
|
+
v
|
|
89
|
+
┌─────────────┐
|
|
90
|
+
│ WGSL Code │ Output: Valid WebGPU shader
|
|
91
|
+
└─────────────┘
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Compilation Pipeline
|
|
97
|
+
|
|
98
|
+
### Phase 1: Parse & Validate
|
|
99
|
+
|
|
100
|
+
**File:** `src/parser.ts`
|
|
101
|
+
**Input:** WebAssembly binary (`Uint8Array`)
|
|
102
|
+
**Output:** `WasmModule` (stack-based IR)
|
|
103
|
+
|
|
104
|
+
**Responsibilities:**
|
|
105
|
+
- Parse Wasm binary format (magic, version, sections)
|
|
106
|
+
- Extract types, imports, functions, tables, memories, globals, exports, code
|
|
107
|
+
- Validate Gasm restrictions:
|
|
108
|
+
- Max 1 memory (no multi-memory)
|
|
109
|
+
- Max 1 table (no multi-table)
|
|
110
|
+
- No imports except globals (built-ins)
|
|
111
|
+
- Memory must be exported as `"memory"`
|
|
112
|
+
- Decode instruction bytecode to IR
|
|
113
|
+
|
|
114
|
+
**Key Functions:**
|
|
115
|
+
```typescript
|
|
116
|
+
export function parseWasm(binary: Uint8Array): WasmModule
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Error Handling:**
|
|
120
|
+
Throws `CompileError` with descriptive message for invalid binaries or Gasm violations.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
### Phase 2: Stack → SSA Conversion
|
|
125
|
+
|
|
126
|
+
**File:** `src/phases.ts` → `phaseStackToSSA()`
|
|
127
|
+
**Input:** `WasmModule`
|
|
128
|
+
**Output:** `SSAModule`
|
|
129
|
+
|
|
130
|
+
**Responsibilities:**
|
|
131
|
+
- Convert stack-based operations to Static Single Assignment (SSA) form
|
|
132
|
+
- Infer types for local variables (from usage patterns)
|
|
133
|
+
- Preserve global definitions and imports
|
|
134
|
+
- Generate unique SSA variable names (`%0`, `%1`, `%2`, ...)
|
|
135
|
+
|
|
136
|
+
**Example:**
|
|
137
|
+
```wasm
|
|
138
|
+
;; WebAssembly (stack-based)
|
|
139
|
+
local.get 0
|
|
140
|
+
i32.const 1
|
|
141
|
+
i32.add
|
|
142
|
+
local.set 0
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
↓
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
// SSA IR
|
|
149
|
+
%0 = local.get 0: i32
|
|
150
|
+
%1 = i32.const 1
|
|
151
|
+
%2 = i32.add %0, %1
|
|
152
|
+
local.set 0, %2
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Key Functions:**
|
|
156
|
+
```typescript
|
|
157
|
+
export function phaseStackToSSA(module: WasmModule): SSAModule
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
### Phase 3: Control Flow Restructuring
|
|
163
|
+
|
|
164
|
+
**File:** `src/relooper.ts`
|
|
165
|
+
**Input:** `SSAModule`
|
|
166
|
+
**Output:** `StructuredModule`
|
|
167
|
+
|
|
168
|
+
**Responsibilities:**
|
|
169
|
+
- Apply the **Relooper algorithm** to restructure control flow
|
|
170
|
+
- Transform unstructured jumps (`br`, `br_if`, `br_table`) into structured loops/blocks
|
|
171
|
+
- Generate WGSL-compatible control structures (`if`, `loop`, `break`, `continue`)
|
|
172
|
+
|
|
173
|
+
**Example:**
|
|
174
|
+
```wasm
|
|
175
|
+
;; WebAssembly (unstructured)
|
|
176
|
+
block $exit
|
|
177
|
+
loop $loop
|
|
178
|
+
local.get 0
|
|
179
|
+
i32.const 10
|
|
180
|
+
i32.lt_s
|
|
181
|
+
br_if $exit
|
|
182
|
+
;; loop body
|
|
183
|
+
br $loop
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
↓
|
|
189
|
+
|
|
190
|
+
```wgsl
|
|
191
|
+
// WGSL (structured)
|
|
192
|
+
loop {
|
|
193
|
+
if (var_0 < 10i) { break; }
|
|
194
|
+
// loop body
|
|
195
|
+
}
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
**Key Functions:**
|
|
199
|
+
```typescript
|
|
200
|
+
export function reloop(module: SSAModule): StructuredModule
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
### Phase 4: Memory Lowering
|
|
206
|
+
|
|
207
|
+
**File:** `src/phases.ts` → `phaseMemoryLowering()`
|
|
208
|
+
**Input:** `StructuredModule`
|
|
209
|
+
**Output:** `StructuredModule` (memory-lowered)
|
|
210
|
+
|
|
211
|
+
**Responsibilities:**
|
|
212
|
+
- Lower sub-word memory operations (i8/i16) to word-aligned access (i32)
|
|
213
|
+
- Generate bit-masking and shifting for unaligned access
|
|
214
|
+
- Preserve i32/i64/f32/f64 memory operations
|
|
215
|
+
|
|
216
|
+
**Example:**
|
|
217
|
+
```wasm
|
|
218
|
+
;; i32.load8_u offset=0 align=1
|
|
219
|
+
i32.load8_u offset=0 align=1
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
↓
|
|
223
|
+
|
|
224
|
+
```wgsl
|
|
225
|
+
// WGSL (lowered to word access)
|
|
226
|
+
let word_addr = offset / 4u;
|
|
227
|
+
let byte_offset = offset % 4u;
|
|
228
|
+
let word = memory[word_addr];
|
|
229
|
+
let byte = (word >> (byte_offset * 8u)) & 0xFFu;
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
**Key Functions:**
|
|
233
|
+
```typescript
|
|
234
|
+
export function phaseMemoryLowering(module: StructuredModule): StructuredModule
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
### Phase 5: WGSL Code Generation
|
|
240
|
+
|
|
241
|
+
**File:** `src/phases.ts` → `phaseWgslCodegen()`
|
|
242
|
+
**Input:** `StructuredModule`
|
|
243
|
+
**Output:** WGSL string
|
|
244
|
+
|
|
245
|
+
**Responsibilities:**
|
|
246
|
+
- Emit WGSL variable declarations (globals, locals)
|
|
247
|
+
- Emit function definitions with signatures
|
|
248
|
+
- Emit main entry point with Gasm built-in parameters:
|
|
249
|
+
- `@builtin(global_invocation_id)` → `global_invocation_id_{x,y,z}`
|
|
250
|
+
- `@builtin(local_invocation_id)` → `local_invocation_id_{x,y,z}`
|
|
251
|
+
- `@builtin(workgroup_id)` → `workgroup_id_{x,y,z}`
|
|
252
|
+
- `@builtin(num_workgroups)` → `num_workgroups_{x,y,z}`
|
|
253
|
+
- Map Wasm instructions to WGSL expressions
|
|
254
|
+
- Generate structured control flow (blocks, loops, conditionals)
|
|
255
|
+
|
|
256
|
+
**Example:**
|
|
257
|
+
```wasm
|
|
258
|
+
(func $add (param i32 i32) (result i32)
|
|
259
|
+
local.get 0
|
|
260
|
+
local.get 1
|
|
261
|
+
i32.add)
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
↓
|
|
265
|
+
|
|
266
|
+
```wgsl
|
|
267
|
+
fn func_0(param_0: i32, param_1: i32) -> i32 {
|
|
268
|
+
return param_0 + param_1;
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**Key Functions:**
|
|
273
|
+
```typescript
|
|
274
|
+
export function phaseWgslCodegen(
|
|
275
|
+
module: StructuredModule,
|
|
276
|
+
options?: CompileOptions
|
|
277
|
+
): string
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## IR Types
|
|
283
|
+
|
|
284
|
+
The compiler uses three IR representations:
|
|
285
|
+
|
|
286
|
+
### 1. WasmModule (Stack-Based IR)
|
|
287
|
+
|
|
288
|
+
**File:** `src/types.ts`
|
|
289
|
+
**Purpose:** Direct representation of WebAssembly binary
|
|
290
|
+
|
|
291
|
+
```typescript
|
|
292
|
+
export interface WasmModule {
|
|
293
|
+
types: WasmType[];
|
|
294
|
+
imports: Import[];
|
|
295
|
+
functions: WasmFunction[];
|
|
296
|
+
tables: Table[];
|
|
297
|
+
memories: Memory[];
|
|
298
|
+
globals: Global[]; // ImportedGlobal | DefinedGlobal
|
|
299
|
+
exports: Export[];
|
|
300
|
+
start?: number;
|
|
301
|
+
elements: Element[];
|
|
302
|
+
dataSegments: DataSegment[];
|
|
303
|
+
customSections: CustomSection[];
|
|
304
|
+
}
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
**Key Properties:**
|
|
308
|
+
- `types`: Function signatures (param/result types)
|
|
309
|
+
- `functions`: Function bodies with stack-based instructions
|
|
310
|
+
- `globals`: Global variables (imported built-ins or definitions)
|
|
311
|
+
- `memories`: Linear memory configuration (initial/max pages)
|
|
312
|
+
- `exports`: Exported functions and memory
|
|
313
|
+
|
|
314
|
+
---
|
|
315
|
+
|
|
316
|
+
### 2. SSAModule (SSA IR)
|
|
317
|
+
|
|
318
|
+
**File:** `src/types.ts`
|
|
319
|
+
**Purpose:** Static Single Assignment form for analysis
|
|
320
|
+
|
|
321
|
+
```typescript
|
|
322
|
+
export interface SSAModule {
|
|
323
|
+
types: WasmType[];
|
|
324
|
+
imports: Import[];
|
|
325
|
+
functions: SSAFunction[];
|
|
326
|
+
tables: Table[];
|
|
327
|
+
memories: Memory[];
|
|
328
|
+
globals: Global[];
|
|
329
|
+
exports: Export[];
|
|
330
|
+
start?: number;
|
|
331
|
+
elements: Element[];
|
|
332
|
+
dataSegments: DataSegment[];
|
|
333
|
+
customSections: CustomSection[];
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export interface SSAFunction {
|
|
337
|
+
typeIndex: number;
|
|
338
|
+
locals: Local[];
|
|
339
|
+
body: SSAInstruction[];
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export interface SSAInstruction {
|
|
343
|
+
opcode: number;
|
|
344
|
+
name: string;
|
|
345
|
+
type?: string;
|
|
346
|
+
operands?: string[];
|
|
347
|
+
result?: string;
|
|
348
|
+
immediates?: unknown[];
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**Key Properties:**
|
|
353
|
+
- `SSAFunction.body`: Instructions with explicit SSA operands/results
|
|
354
|
+
- `SSAInstruction.result`: SSA variable name (e.g., `%0`, `%1`)
|
|
355
|
+
- `SSAInstruction.operands`: SSA variable dependencies (e.g., `["%0", "%1"]`)
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
### 3. StructuredModule (Structured IR)
|
|
360
|
+
|
|
361
|
+
**File:** `src/types.ts`
|
|
362
|
+
**Purpose:** Structured control flow for WGSL generation
|
|
363
|
+
|
|
364
|
+
```typescript
|
|
365
|
+
export interface StructuredModule {
|
|
366
|
+
types: WasmType[];
|
|
367
|
+
imports: Import[];
|
|
368
|
+
functions: StructuredFunction[];
|
|
369
|
+
tables: Table[];
|
|
370
|
+
memories: Memory[];
|
|
371
|
+
globals: Global[];
|
|
372
|
+
exports: Export[];
|
|
373
|
+
start?: number;
|
|
374
|
+
elements: Element[];
|
|
375
|
+
dataSegments: DataSegment[];
|
|
376
|
+
customSections: CustomSection[];
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export interface StructuredFunction {
|
|
380
|
+
typeIndex: number;
|
|
381
|
+
locals: Local[];
|
|
382
|
+
body: StructuredInstruction[];
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
export interface StructuredInstruction {
|
|
386
|
+
opcode: number;
|
|
387
|
+
name: string;
|
|
388
|
+
type?: string;
|
|
389
|
+
operands?: string[];
|
|
390
|
+
result?: string;
|
|
391
|
+
immediates?: unknown[];
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
**Key Properties:**
|
|
396
|
+
- Control flow is fully structured (no `br`, `br_if`, `br_table`)
|
|
397
|
+
- Instructions use WGSL-compatible constructs (`if`, `loop`, `break`)
|
|
398
|
+
- Memory operations are word-aligned (i32/i64/f32/f64 only)
|
|
399
|
+
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
## Instruction Mapping
|
|
403
|
+
|
|
404
|
+
The compiler maps 120+ WebAssembly instructions to WGSL equivalents. See the full table in the [Instruction Set Reference](../../docs/instruction-set.md).
|
|
405
|
+
|
|
406
|
+
### Quick Reference
|
|
407
|
+
|
|
408
|
+
| Category | Example Instructions | WGSL Equivalent |
|
|
409
|
+
|----------|---------------------|-----------------|
|
|
410
|
+
| **Arithmetic** | `i32.add`, `f32.mul` | `a + b`, `a * b` |
|
|
411
|
+
| **Bitwise** | `i32.and`, `i32.shl` | `a & b`, `a << (b & 31u)` |
|
|
412
|
+
| **Comparisons** | `i32.lt_s`, `f32.eq` | `a < b`, `a == b` |
|
|
413
|
+
| **Memory** | `i32.load`, `i32.store8` | `memory[addr/4u]`, bit-masking |
|
|
414
|
+
| **Conversions** | `i32.trunc_f32_s`, `f32.convert_i32_u` | `i32(trunc(a))`, `f32(u32(a))` |
|
|
415
|
+
| **Control Flow** | `block`, `loop`, `br_if` | `{ ... }`, `loop { ... }`, `if (c) { break; }` |
|
|
416
|
+
| **Variables** | `local.get`, `global.set` | `var_N`, `global_N = val` |
|
|
417
|
+
| **Special** | `select`, `memory.size` | `select(a, b, c)`, `arrayLength(&memory)` |
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## Gasm Conformance
|
|
422
|
+
|
|
423
|
+
The compiler implements **Gasm v0.1 L0 (Core)** conformance:
|
|
424
|
+
|
|
425
|
+
### Conformance Levels
|
|
426
|
+
|
|
427
|
+
| Level | Features | Status |
|
|
428
|
+
|-------|----------|--------|
|
|
429
|
+
| **L0 (Core)** | Scalar operations (i32, i64, f32, f64) | ✅ Implemented |
|
|
430
|
+
| **L1 (SIMD)** | 128-bit SIMD operations (v128) | 🚧 Planned |
|
|
431
|
+
| **L2 (Extended)** | Atomics + Relaxed SIMD | 🚧 Planned |
|
|
432
|
+
|
|
433
|
+
### Gasm Restrictions (Section 10)
|
|
434
|
+
|
|
435
|
+
The compiler enforces these restrictions during Phase 1 validation:
|
|
436
|
+
|
|
437
|
+
1. **Single Memory**: Max 1 memory, must be exported as `"memory"`
|
|
438
|
+
2. **Single Table**: Max 1 table (for indirect calls)
|
|
439
|
+
3. **No Imports** (except globals): Only global imports allowed (Gasm built-ins)
|
|
440
|
+
4. **Deterministic Execution**: No `unreachable` or trapping operations in production code
|
|
441
|
+
5. **Structured Control Flow**: All `br`, `br_if`, `br_table` must be restructurable (Phase 3)
|
|
442
|
+
|
|
443
|
+
### Gasm Built-in Globals
|
|
444
|
+
|
|
445
|
+
The compiler automatically maps WGSL built-ins to global imports:
|
|
446
|
+
|
|
447
|
+
| Global Name | WGSL Built-in | Type |
|
|
448
|
+
|-------------|---------------|------|
|
|
449
|
+
| `global_invocation_id_x` | `@builtin(global_invocation_id).x` | `u32` |
|
|
450
|
+
| `global_invocation_id_y` | `@builtin(global_invocation_id).y` | `u32` |
|
|
451
|
+
| `global_invocation_id_z` | `@builtin(global_invocation_id).z` | `u32` |
|
|
452
|
+
| `local_invocation_id_x` | `@builtin(local_invocation_id).x` | `u32` |
|
|
453
|
+
| `local_invocation_id_y` | `@builtin(local_invocation_id).y` | `u32` |
|
|
454
|
+
| `local_invocation_id_z` | `@builtin(local_invocation_id).z` | `u32` |
|
|
455
|
+
| `workgroup_id_x` | `@builtin(workgroup_id).x` | `u32` |
|
|
456
|
+
| `workgroup_id_y` | `@builtin(workgroup_id).y` | `u32` |
|
|
457
|
+
| `workgroup_id_z` | `@builtin(workgroup_id).z` | `u32` |
|
|
458
|
+
| `num_workgroups_x` | `@builtin(num_workgroups).x` | `u32` |
|
|
459
|
+
| `num_workgroups_y` | `@builtin(num_workgroups).y` | `u32` |
|
|
460
|
+
| `num_workgroups_z` | `@builtin(num_workgroups).z` | `u32` |
|
|
461
|
+
|
|
462
|
+
**Example:**
|
|
463
|
+
```wasm
|
|
464
|
+
(import "gasm" "global_invocation_id_x" (global $gid_x i32))
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
↓
|
|
468
|
+
|
|
469
|
+
```wgsl
|
|
470
|
+
@compute @workgroup_size(64)
|
|
471
|
+
fn main(
|
|
472
|
+
@builtin(global_invocation_id) global_invocation_id: vec3<u32>,
|
|
473
|
+
// ... other built-ins
|
|
474
|
+
) {
|
|
475
|
+
var global_invocation_id_x: u32 = global_invocation_id.x;
|
|
476
|
+
// ... use in function body
|
|
477
|
+
}
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
---
|
|
481
|
+
|
|
482
|
+
## Usage
|
|
483
|
+
|
|
484
|
+
### Basic Compilation
|
|
485
|
+
|
|
486
|
+
```typescript
|
|
487
|
+
import { compile } from "@gasm-compiler/core";
|
|
488
|
+
|
|
489
|
+
// Load WebAssembly binary
|
|
490
|
+
const wasmBytes = await Deno.readFile("shader.wasm");
|
|
491
|
+
|
|
492
|
+
// Compile to WGSL
|
|
493
|
+
const wgslCode = compile(wasmBytes);
|
|
494
|
+
|
|
495
|
+
// Use with WebGPU
|
|
496
|
+
const shaderModule = device.createShaderModule({ code: wgslCode });
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
### With Options
|
|
500
|
+
|
|
501
|
+
```typescript
|
|
502
|
+
import { compile, CompileOptions } from "@gasm-compiler/core";
|
|
503
|
+
|
|
504
|
+
const options: CompileOptions = {
|
|
505
|
+
workgroupSize: [128, 1, 1], // Default: [64, 1, 1]
|
|
506
|
+
debug: true, // Emit debug comments
|
|
507
|
+
mathExtension: true, // Enable gasm:math built-ins
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
const wgslCode = compile(wasmBytes, options);
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### Math Extension (gasm:math)
|
|
514
|
+
|
|
515
|
+
The `mathExtension` option enables WGSL built-in math functions to be called directly from WebAssembly via imports from the `"gasm"` module:
|
|
516
|
+
|
|
517
|
+
```typescript
|
|
518
|
+
import { compile } from "@gasm-compiler/core";
|
|
519
|
+
|
|
520
|
+
const wgslCode = compile(wasmBytes, {
|
|
521
|
+
mathExtension: true, // Enable all levels (M0, M1, M2)
|
|
522
|
+
// or: mathExtension: "M0" // Core scalar functions only
|
|
523
|
+
// or: mathExtension: "M1" // Core + vector functions
|
|
524
|
+
// or: mathExtension: "M2" // All functions
|
|
525
|
+
});
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
When enabled, imports like `(import "gasm" "sin" (func ...))` are compiled to direct WGSL built-in calls like `sin(...)` instead of function calls.
|
|
529
|
+
|
|
530
|
+
**Math Levels:**
|
|
531
|
+
- **M0 (Core)**: Scalar functions (sin, cos, sqrt, abs, min, max, clamp, etc.)
|
|
532
|
+
- **M1 (Vector)**: Geometric functions (length, dot, cross, normalize, reflect, etc.)
|
|
533
|
+
- **M2 (Advanced)**: modf, frexp, ldexp, degrees, radians, bit manipulation
|
|
534
|
+
|
|
535
|
+
### Error Handling
|
|
536
|
+
|
|
537
|
+
```typescript
|
|
538
|
+
import { compile, isCompileError } from "@gasm-compiler/core";
|
|
539
|
+
|
|
540
|
+
try {
|
|
541
|
+
const wgslCode = compile(wasmBytes);
|
|
542
|
+
console.log("Compilation successful!");
|
|
543
|
+
} catch (error) {
|
|
544
|
+
if (isCompileError(error)) {
|
|
545
|
+
console.error("Compile Error:", error.message);
|
|
546
|
+
if (error.location) {
|
|
547
|
+
console.error(` at line ${error.location.line}, column ${error.location.column}`);
|
|
548
|
+
}
|
|
549
|
+
} else {
|
|
550
|
+
throw error; // Unexpected error
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
## Testing
|
|
558
|
+
|
|
559
|
+
### Running Tests
|
|
560
|
+
|
|
561
|
+
```bash
|
|
562
|
+
# Run all tests
|
|
563
|
+
pnpm test:core
|
|
564
|
+
|
|
565
|
+
# Or directly with Deno
|
|
566
|
+
cd packages/core
|
|
567
|
+
deno test --allow-all
|
|
568
|
+
|
|
569
|
+
# Run specific test file
|
|
570
|
+
deno test tests/compiler_test.ts --allow-all
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
### Test Organization
|
|
574
|
+
|
|
575
|
+
Tests are organized by phase:
|
|
576
|
+
|
|
577
|
+
```
|
|
578
|
+
packages/core/tests/
|
|
579
|
+
├── compiler_test.ts # Integration tests (full pipeline)
|
|
580
|
+
└── fixtures/ # Test data files (future)
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
**Current Test Coverage (Session 3):**
|
|
584
|
+
- ✅ **Phase 1: Parser validation** (26 tests)
|
|
585
|
+
- ✅ **Phase 2-5: Integration tests** (12 tests)
|
|
586
|
+
- ✅ **i32 Arithmetic** (18 tests)
|
|
587
|
+
- ✅ **i32 Bitwise** (32 tests)
|
|
588
|
+
- ✅ **i32 Comparison** (20 tests)
|
|
589
|
+
- ✅ **i64 Arithmetic** (19 tests)
|
|
590
|
+
- ✅ **i64 Bitwise** (32 tests)
|
|
591
|
+
- ✅ **i64 Comparison** (20 tests)
|
|
592
|
+
- ✅ **f32 Arithmetic** (48 tests)
|
|
593
|
+
- ✅ **f64 Arithmetic** (48 tests)
|
|
594
|
+
- ✅ **Float Comparison** (17 tests)
|
|
595
|
+
- ✅ **Float Edge Cases** (18 tests)
|
|
596
|
+
- ✅ **Type Conversions** (53 tests: 16 original + 37 new comprehensive tests)
|
|
597
|
+
- ✅ **Control Flow** (9 tests)
|
|
598
|
+
- ✅ **Memory Operations** (14 tests)
|
|
599
|
+
- ✅ **Functions, Stack, Constants** (19 tests)
|
|
600
|
+
- ✅ **Error Handling** (19 tests)
|
|
601
|
+
- ✅ **WGSL Output Validation** (40 tests)
|
|
602
|
+
- ✅ **Global & Options** (2 tests)
|
|
603
|
+
|
|
604
|
+
**Total:** 471 tests passing (414ms execution time)
|
|
605
|
+
**Test Files:** 23 organized by instruction category
|
|
606
|
+
|
|
607
|
+
### Adding New Tests
|
|
608
|
+
|
|
609
|
+
```typescript
|
|
610
|
+
import { assertEquals } from "jsr:@std/assert";
|
|
611
|
+
import { compile } from "../src/mod.ts";
|
|
612
|
+
|
|
613
|
+
Deno.test("Compiler - Feature Name", () => {
|
|
614
|
+
// Create WebAssembly binary (WAT → Wasm)
|
|
615
|
+
const wat = `
|
|
616
|
+
(module
|
|
617
|
+
(func (export "add") (param i32 i32) (result i32)
|
|
618
|
+
local.get 0
|
|
619
|
+
local.get 1
|
|
620
|
+
i32.add))
|
|
621
|
+
`;
|
|
622
|
+
const wasmBytes = wat2wasm(wat); // Use wat2wasm utility
|
|
623
|
+
|
|
624
|
+
// Compile to WGSL
|
|
625
|
+
const wgslCode = compile(wasmBytes);
|
|
626
|
+
|
|
627
|
+
// Verify output
|
|
628
|
+
assertEquals(wgslCode.includes("param_0 + param_1"), true);
|
|
629
|
+
});
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
---
|
|
633
|
+
|
|
634
|
+
## API Reference
|
|
635
|
+
|
|
636
|
+
### Main API
|
|
637
|
+
|
|
638
|
+
#### `compile(source: Uint8Array, options?: CompileOptions): string`
|
|
639
|
+
|
|
640
|
+
Compiles a WebAssembly binary to WGSL.
|
|
641
|
+
|
|
642
|
+
**Parameters:**
|
|
643
|
+
- `source`: WebAssembly binary (Uint8Array)
|
|
644
|
+
- `options`: Optional compilation options
|
|
645
|
+
|
|
646
|
+
**Returns:** WGSL shader code (string)
|
|
647
|
+
|
|
648
|
+
**Throws:** `CompileError` if validation or transformation fails
|
|
649
|
+
|
|
650
|
+
---
|
|
651
|
+
|
|
652
|
+
### Types
|
|
653
|
+
|
|
654
|
+
#### `CompileOptions`
|
|
655
|
+
|
|
656
|
+
```typescript
|
|
657
|
+
export interface CompileOptions {
|
|
658
|
+
workgroupSize?: [number, number, number]; // Default: [64, 1, 1]
|
|
659
|
+
debug?: boolean; // Emit debug comments (default: false)
|
|
660
|
+
}
|
|
661
|
+
```
|
|
662
|
+
|
|
663
|
+
#### `CompileError`
|
|
664
|
+
|
|
665
|
+
```typescript
|
|
666
|
+
export interface CompileError {
|
|
667
|
+
type: "CompileError";
|
|
668
|
+
message: string;
|
|
669
|
+
location?: { line: number; column: number };
|
|
670
|
+
context?: string;
|
|
671
|
+
}
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
#### `isCompileError(error: unknown): error is CompileError`
|
|
675
|
+
|
|
676
|
+
Type guard to check if an error is a `CompileError`.
|
|
677
|
+
|
|
678
|
+
---
|
|
679
|
+
|
|
680
|
+
### Internal APIs
|
|
681
|
+
|
|
682
|
+
These are exported for testing but not intended for public use:
|
|
683
|
+
|
|
684
|
+
- `parseWasm(binary: Uint8Array): WasmModule` — Parse Wasm binary
|
|
685
|
+
- `phaseStackToSSA(module: WasmModule): SSAModule` — Convert to SSA
|
|
686
|
+
- `reloop(module: SSAModule): StructuredModule` — Restructure control flow
|
|
687
|
+
- `phaseMemoryLowering(module: StructuredModule): StructuredModule` — Lower memory ops
|
|
688
|
+
- `phaseWgslCodegen(module: StructuredModule, options?: CompileOptions): string` — Generate WGSL
|
|
689
|
+
|
|
690
|
+
---
|
|
691
|
+
|
|
692
|
+
## Contributing
|
|
693
|
+
|
|
694
|
+
See [AGENTS.md](../../AGENTS.md) for guidelines on working with the core compiler.
|
|
695
|
+
|
|
696
|
+
### Development Workflow
|
|
697
|
+
|
|
698
|
+
1. **Write tests first** for new features
|
|
699
|
+
2. **Run tests** with `pnpm test:core`
|
|
700
|
+
3. **Keep platform-agnostic** — no Deno-specific APIs in core logic
|
|
701
|
+
4. **Follow TypeScript strict mode** — all types must be explicit
|
|
702
|
+
5. **Document public APIs** — JSDoc for all exported functions
|
|
703
|
+
|
|
704
|
+
---
|
|
705
|
+
|
|
706
|
+
## License
|
|
707
|
+
|
|
708
|
+
MIT License — See [LICENSE](../../LICENSE) for details.
|
|
709
|
+
|
|
710
|
+
---
|
|
711
|
+
|
|
712
|
+
## Related Documentation
|
|
713
|
+
|
|
714
|
+
- [Gasm Specification v0.1](../../spec/gasm-v0.1.md) — GPU-executable WebAssembly spec
|
|
715
|
+
- [Instruction Set Reference](../../docs/instruction-set.md) — Detailed instruction mappings
|
|
716
|
+
- [AGENTS.md](../../AGENTS.md) — Development guidelines for agents
|
|
717
|
+
|
|
718
|
+
---
|
|
719
|
+
|
|
720
|
+
**Last Updated:** December 2025
|