Skip to content

Commit 1acc9ee

Browse files
committed
add WasmRaw, generate block type, support labels as numbers
1 parent 67006ae commit 1acc9ee

File tree

3 files changed

+65
-12
lines changed

3 files changed

+65
-12
lines changed

src/wasm-compiler/wasm-util/builder.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
intComparisonOp,
1414
intConversionOp,
1515
intTestOp,
16+
WasmRaw,
1617
type WasmBinaryOp,
1718
type WasmBlock,
1819
type WasmBlockType,
@@ -233,13 +234,16 @@ const f64 = {
233234
} satisfies Builder<"f64">;
234235

235236
const local = {
236-
get: (label: WasmLabel): WasmLocalGet => ({ op: "local.get", label }),
237-
set: (label: WasmLabel, right: WasmNumeric): WasmLocalSet => ({
237+
get: (label: WasmLabel | number): WasmLocalGet => ({
238+
op: "local.get",
239+
label,
240+
}),
241+
set: (label: WasmLabel | number, right: WasmNumeric): WasmLocalSet => ({
238242
op: "local.set",
239243
label,
240244
right,
241245
}),
242-
tee: (label: WasmLabel, right: WasmNumeric): WasmLocalTee => ({
246+
tee: (label: WasmLabel | number, right: WasmNumeric): WasmLocalTee => ({
243247
op: "local.tee",
244248
label,
245249
right,
@@ -588,6 +592,11 @@ const wasm = {
588592

589593
return buildBlock(bodies.length - 1);
590594
},
595+
596+
raw: (
597+
codeFragments: TemplateStringsArray,
598+
...interpolations: (number | string | WasmInstruction | WasmInstruction[])[]
599+
): WasmRaw => ({ op: "raw", codeFragments, interpolations }),
591600
};
592601

593602
// This maps all WASM instructions to a visitor method name that will
@@ -695,6 +704,8 @@ const instrToMethodMap = {
695704
export: "visitExportOp",
696705
start: "visitStartOp",
697706
module: "visitModuleOp",
707+
708+
raw: "visitRaw",
698709
} as const satisfies Record<WasmInstruction["op"], string>;
699710

700711
// ------------------------ WASM Visitor Interface ----------------------------

src/wasm-compiler/wasm-util/types.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,13 +222,13 @@ export type WasmNumeric =
222222

223223
export type WasmLocalSet = {
224224
op: "local.set";
225-
label: WasmLabel;
225+
label: WasmLabel | number;
226226
right: WasmNumeric;
227227
};
228-
export type WasmLocalGet = { op: "local.get"; label: WasmLabel };
228+
export type WasmLocalGet = { op: "local.get"; label: WasmLabel | number };
229229
export type WasmLocalTee = {
230230
op: "local.tee";
231-
label: WasmLabel;
231+
label: WasmLabel | number;
232232
right: WasmNumeric;
233233
};
234234
export type WasmGlobalSet = {
@@ -396,9 +396,17 @@ export type WasmModuleInstruction =
396396
| WasmStart
397397
| WasmModule;
398398

399+
// meant to be used with wasm.raw (tagged template)
400+
export type WasmRaw = {
401+
op: "raw";
402+
codeFragments: TemplateStringsArray;
403+
interpolations: (number | string | WasmInstruction | WasmInstruction[])[];
404+
};
405+
399406
export type WasmInstruction =
400407
| WasmNumeric
401408
| WasmMemory
402409
| WasmControl
403410
| WasmVariable
404-
| WasmModuleInstruction;
411+
| WasmModuleInstruction
412+
| WasmRaw;

src/wasm-compiler/wasm-util/watGenerator.ts

Lines changed: 39 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { instrToMethodMap, type WatVisitor } from "./builder";
22
import type {
33
WasmBlock,
4+
WasmBlockType,
45
WasmBr,
56
WasmBrTable,
67
WasmCall,
@@ -25,6 +26,7 @@ import type {
2526
WasmModule,
2627
WasmNop,
2728
WasmNumericType,
29+
WasmRaw,
2830
WasmReturn,
2931
WasmSelect,
3032
WasmStart,
@@ -79,18 +81,31 @@ export class WatGenerator implements WatVisitor {
7981
}
8082

8183
// Control visitor methods
84+
private visitBlockType(type: WasmBlockType): string {
85+
const params = type.paramTypes.map((param) => `(param ${param})`).join(" ");
86+
const results = type.resultTypes
87+
.map((result) => `(result ${result})`)
88+
.join(" ");
89+
const locals =
90+
type.localTypes?.map((local) => `(local ${local})`).join(" ") ?? "";
91+
return `${params} ${results} ${locals}`;
92+
}
93+
8294
visitBlockOp(instruction: WasmBlock): string {
8395
const label = instruction.label ?? "";
96+
const typeStr = this.visitBlockType(instruction.blockType);
8497
const body = instruction.body.map((instr) => this.visit(instr)).join(" ");
85-
return `(${instruction.op} ${label} ${body})`;
98+
return `(${instruction.op} ${label} ${typeStr} ${body})`;
8699
}
87100
visitLoopOp(instruction: WasmLoop): string {
88101
const label = instruction.label ?? "";
102+
const typeStr = this.visitBlockType(instruction.blockType);
89103
const body = instruction.body.map((instr) => this.visit(instr)).join(" ");
90-
return `(${instruction.op} ${label} ${body})`;
104+
return `(${instruction.op} ${label} ${typeStr} ${body})`;
91105
}
92106
visitIfOp(instruction: WasmIf): string {
93107
const label = instruction.label ?? "";
108+
const typeStr = this.visitBlockType(instruction.blockType);
94109
const condition = this.visit(instruction.predicate);
95110
const thenBody = instruction.thenBody
96111
.map((instr) => this.visit(instr))
@@ -100,9 +115,9 @@ export class WatGenerator implements WatVisitor {
100115
.join(" ");
101116

102117
if (elseBody) {
103-
return `(if ${label} ${condition} (then ${thenBody}) (else ${elseBody}))`;
118+
return `(if ${label} ${typeStr} ${condition} (then ${thenBody}) (else ${elseBody}))`;
104119
} else {
105-
return `(if ${label} ${condition} (then ${thenBody}))`;
120+
return `(if ${label} ${typeStr} ${condition} (then ${thenBody}))`;
106121
}
107122
}
108123
visitUnreachableOp(instruction: WasmUnreachable): string {
@@ -189,7 +204,9 @@ export class WatGenerator implements WatVisitor {
189204
.map(([name, type]) => `(param ${name} ${type})`)
190205
.join(" ");
191206

192-
const results = `(result ${instruction.funcType.resultTypes.join(" ")})`;
207+
const results = instruction.funcType.resultTypes.length
208+
? `(result ${instruction.funcType.resultTypes.join(" ")})`
209+
: "";
193210

194211
const locals = Object.entries(instruction.funcType.localTypes)
195212
.map(([name, type]) => `(local ${name} ${type})`)
@@ -239,4 +256,21 @@ export class WatGenerator implements WatVisitor {
239256

240257
return `(${instruction.op}\n${imports}\n${globals}\n${datas}\n${funcs}\n${startFunc}\n${exports})`;
241258
}
259+
260+
visitRaw(instruction: WasmRaw): string {
261+
let code = "";
262+
for (let i = 0; i < instruction.interpolations.length; i++) {
263+
code += instruction.codeFragments[i];
264+
const interp = instruction.interpolations[i];
265+
if (typeof interp === "string" || typeof interp === "number") {
266+
code += interp.toString();
267+
} else if (Array.isArray(interp)) {
268+
code += interp.map((instr) => this.visit(instr)).join(" ");
269+
} else {
270+
code += this.visit(interp);
271+
}
272+
}
273+
code += instruction.codeFragments[instruction.interpolations.length];
274+
return code;
275+
}
242276
}

0 commit comments

Comments
 (0)