gofront 1.6.0 → 1.7.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/README.md +35 -39
- package/package.json +37 -4
- package/src/backend/js/expressions.js +559 -144
- package/src/backend/js/index.js +174 -49
- package/src/backend/js/runtime.js +1518 -54
- package/src/backend/js/statements.js +91 -73
- package/src/backend/js/stdlib/base64.js +12 -0
- package/src/backend/js/stdlib/binary.js +102 -0
- package/src/backend/js/stdlib/bits.js +15 -1
- package/src/backend/js/stdlib/builder.js +28 -9
- package/src/backend/js/stdlib/bytes.js +75 -18
- package/src/backend/js/stdlib/errors.js +25 -1
- package/src/backend/js/stdlib/fmt.js +70 -13
- package/src/backend/js/stdlib/hex.js +17 -0
- package/src/backend/js/stdlib/html.js +1 -1
- package/src/backend/js/stdlib/index.js +28 -0
- package/src/backend/js/stdlib/io.js +105 -3
- package/src/backend/js/stdlib/json.js +972 -0
- package/src/backend/js/stdlib/math.js +13 -1
- package/src/backend/js/stdlib/path.js +18 -4
- package/src/backend/js/stdlib/rand.js +10 -5
- package/src/backend/js/stdlib/sha256.js +12 -0
- package/src/backend/js/stdlib/simd.js +24 -0
- package/src/backend/js/stdlib/slices.js +52 -26
- package/src/backend/js/stdlib/strconv.js +21 -5
- package/src/backend/js/stdlib/strings.js +148 -15
- package/src/backend/js/stdlib/sync.js +13 -0
- package/src/backend/js/stdlib/time.js +90 -19
- package/src/backend/js/stdlib/unicode.js +2 -2
- package/src/backend/wasm/boundary.js +1225 -41
- package/src/backend/wasm/const-fold.js +205 -0
- package/src/backend/wasm/emit-builtins.js +220 -76
- package/src/backend/wasm/emit-exprs.js +475 -276
- package/src/backend/wasm/emit-maps.js +144 -8
- package/src/backend/wasm/emit-stdlib.js +12 -3005
- package/src/backend/wasm/emit-stmts.js +264 -270
- package/src/backend/wasm/emit.js +124 -87
- package/src/backend/wasm/encode.js +140 -29
- package/src/backend/wasm/index.js +1001 -32
- package/src/backend/wasm/optimize.js +17 -6
- package/src/backend/wasm/stdlib/bytes.js +5039 -0
- package/src/backend/wasm/stdlib/core.js +8903 -0
- package/src/backend/wasm/stdlib/index.js +43 -0
- package/src/backend/wasm/stdlib/io.js +2161 -0
- package/src/backend/wasm/stdlib/packages.js +2400 -0
- package/src/backend/wasm/stdlib/pure.js +720 -0
- package/src/backend/wasm/stdlib/simd.js +234 -0
- package/src/backend/wasm/stdlib/time.js +1200 -0
- package/src/backend/wasm/types.js +174 -1
- package/src/backend/wasm/wat.js +37 -0
- package/src/cli-core.js +1 -1
- package/src/compiler.js +18 -4
- package/src/dts-parser.js +150 -140
- package/src/index.js +2 -6
- package/src/lexer.js +80 -29
- package/src/lower/boxing.js +1 -7
- package/src/lower/captures.js +2 -6
- package/src/lower/embedding.js +2 -1
- package/src/lower/ownership.js +30 -9
- package/src/minifier.js +20 -68
- package/src/parser/declarations.js +3 -6
- package/src/parser/expressions.js +3 -8
- package/src/parser/index.js +18 -3
- package/src/parser/statements.js +25 -38
- package/src/parser/struct-tag.js +144 -0
- package/src/parser/types.js +64 -8
- package/src/resolver.js +2 -27
- package/src/templ-lexer.js +29 -63
- package/src/templ-parser.js +22 -45
- package/src/typechecker/assignability.js +126 -13
- package/src/typechecker/expressions.js +168 -16
- package/src/typechecker/index.js +35 -8
- package/src/typechecker/resolve.js +187 -8
- package/src/typechecker/statements.js +68 -9
- package/src/typechecker/stdlib/core.js +280 -89
- package/src/typechecker/stdlib/extended.js +490 -1
- package/src/typechecker/stdlib/simd.js +73 -0
- package/src/typechecker/stdlib.js +2 -0
- package/src/typechecker/types.js +362 -9
- package/src/vendor.js +86 -11
package/src/backend/wasm/emit.js
CHANGED
|
@@ -8,8 +8,16 @@ import { BuiltinsEmitter } from "./emit-builtins.js";
|
|
|
8
8
|
import { ExprsEmitter } from "./emit-exprs.js";
|
|
9
9
|
import { MapsEmitter } from "./emit-maps.js";
|
|
10
10
|
import { SharedEmitter } from "./emit-shared.js";
|
|
11
|
-
import { StdlibEmitter } from "./emit-stdlib.js";
|
|
12
11
|
import { StmtsEmitter } from "./emit-stmts.js";
|
|
12
|
+
import {
|
|
13
|
+
BytesEmitter,
|
|
14
|
+
ExtendedPackagesEmitter,
|
|
15
|
+
IoEmitter,
|
|
16
|
+
PurePackagesEmitter,
|
|
17
|
+
SimdEmitter,
|
|
18
|
+
StdlibCoreEmitter,
|
|
19
|
+
TimeEmitter,
|
|
20
|
+
} from "./stdlib/index.js";
|
|
13
21
|
import {
|
|
14
22
|
isArrayType,
|
|
15
23
|
isPointerToStruct,
|
|
@@ -34,7 +42,14 @@ export class FunctionEmitter {
|
|
|
34
42
|
this.mod.lowerResult?.captures?.get(
|
|
35
43
|
this.rootFuncDecl._sourceDecl ?? this.rootFuncDecl,
|
|
36
44
|
) ?? null;
|
|
37
|
-
this.mutatedCaptures = this.captureAnalysis?.mutatedCaptures ??
|
|
45
|
+
this.mutatedCaptures = new Set(this.captureAnalysis?.mutatedCaptures ?? []);
|
|
46
|
+
const lowerBoxed =
|
|
47
|
+
this.mod.lowerResult?.boxedVars?.get(
|
|
48
|
+
this.rootFuncDecl._sourceDecl ?? this.rootFuncDecl,
|
|
49
|
+
) ?? [];
|
|
50
|
+
for (const name of lowerBoxed) {
|
|
51
|
+
this.mutatedCaptures.add(name);
|
|
52
|
+
}
|
|
38
53
|
|
|
39
54
|
this.capturedNames = this.funcDecl._funcLit
|
|
40
55
|
? Array.from(
|
|
@@ -126,33 +141,7 @@ export class FunctionEmitter {
|
|
|
126
141
|
return;
|
|
127
142
|
}
|
|
128
143
|
|
|
129
|
-
|
|
130
|
-
if (namedReturns && namedReturns.length > 0) {
|
|
131
|
-
this.namedReturnVars = [];
|
|
132
|
-
for (let i = 0; i < namedReturns.length; i++) {
|
|
133
|
-
const r = namedReturns[i];
|
|
134
|
-
const isBlank = !r.name || r.name === "_";
|
|
135
|
-
const varName = isBlank ? `__ret_blank$${i}` : r.name;
|
|
136
|
-
const wType = this.toWasmType(r.type);
|
|
137
|
-
const localIdx = this.allocLocal(varName, wType, r.type, isBlank);
|
|
138
|
-
this.namedReturnVars.push({
|
|
139
|
-
name: varName,
|
|
140
|
-
localIdx,
|
|
141
|
-
type: wType,
|
|
142
|
-
goType: r.type,
|
|
143
|
-
isBlank,
|
|
144
|
-
});
|
|
145
|
-
this.emitZeroValue(r.type, wType);
|
|
146
|
-
const localInfo = this.locals.get(varName);
|
|
147
|
-
if (localInfo?.isBoxed) {
|
|
148
|
-
this.pushInstruction({
|
|
149
|
-
op: "struct.new",
|
|
150
|
-
typeIndex: localInfo.boxInfo.typeIndex,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
this.pushInstruction({ op: "local.set", index: localIdx });
|
|
154
|
-
}
|
|
155
|
-
}
|
|
144
|
+
this._initNamedReturns();
|
|
156
145
|
|
|
157
146
|
const needsOobBlock = this._needsOobBlock(body);
|
|
158
147
|
if (needsOobBlock) {
|
|
@@ -181,34 +170,38 @@ export class FunctionEmitter {
|
|
|
181
170
|
}
|
|
182
171
|
}
|
|
183
172
|
|
|
184
|
-
|
|
173
|
+
_initNamedReturns() {
|
|
185
174
|
const namedReturns = this.funcDecl.returnType?._namedReturns;
|
|
186
|
-
if (namedReturns
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
175
|
+
if (!namedReturns?.length) return false;
|
|
176
|
+
this.namedReturnVars = [];
|
|
177
|
+
for (let i = 0; i < namedReturns.length; i++) {
|
|
178
|
+
const r = namedReturns[i];
|
|
179
|
+
const isBlank = !r.name || r.name === "_";
|
|
180
|
+
const varName = isBlank ? `__ret_blank$${i}` : r.name;
|
|
181
|
+
const wType = this.toWasmType(r.type);
|
|
182
|
+
const localIdx = this.allocLocal(varName, wType, r.type, isBlank);
|
|
183
|
+
this.namedReturnVars.push({
|
|
184
|
+
name: varName,
|
|
185
|
+
localIdx,
|
|
186
|
+
type: wType,
|
|
187
|
+
goType: r.type,
|
|
188
|
+
isBlank,
|
|
189
|
+
});
|
|
190
|
+
this.emitZeroValue(r.type, wType);
|
|
191
|
+
const localInfo = this.locals.get(varName);
|
|
192
|
+
if (localInfo?.isBoxed) {
|
|
193
|
+
this.pushInstruction({
|
|
194
|
+
op: "struct.new",
|
|
195
|
+
typeIndex: localInfo.boxInfo.typeIndex,
|
|
200
196
|
});
|
|
201
|
-
this.emitZeroValue(r.type, wType);
|
|
202
|
-
const localInfo = this.locals.get(varName);
|
|
203
|
-
if (localInfo?.isBoxed) {
|
|
204
|
-
this.pushInstruction({
|
|
205
|
-
op: "struct.new",
|
|
206
|
-
typeIndex: localInfo.boxInfo.typeIndex,
|
|
207
|
-
});
|
|
208
|
-
}
|
|
209
|
-
this.pushInstruction({ op: "local.set", index: localIdx });
|
|
210
197
|
}
|
|
211
|
-
|
|
198
|
+
this.pushInstruction({ op: "local.set", index: localIdx });
|
|
199
|
+
}
|
|
200
|
+
return true;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
_emitFunctionBodyWithDefer(body) {
|
|
204
|
+
if (!this._initNamedReturns() && this.returnTypes.length > 0) {
|
|
212
205
|
this.returnTempLocals = [];
|
|
213
206
|
for (let i = 0; i < this.returnTypes.length; i++) {
|
|
214
207
|
const wType = this.returnTypes[i];
|
|
@@ -662,36 +655,27 @@ export class FunctionEmitter {
|
|
|
662
655
|
return null;
|
|
663
656
|
}
|
|
664
657
|
|
|
665
|
-
|
|
658
|
+
_buildEnvFields(capturedNames) {
|
|
666
659
|
const envFields = [];
|
|
667
|
-
for (const name of
|
|
660
|
+
for (const name of capturedNames) {
|
|
668
661
|
const isBoxed = this.mutatedCaptures.has(name);
|
|
669
662
|
const goType = this._findCapturedVarGoType(name);
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
typeIndex: boxInfo.typeIndex,
|
|
681
|
-
},
|
|
682
|
-
});
|
|
683
|
-
} else {
|
|
684
|
-
const wType = this.toWasmType(goType);
|
|
685
|
-
envFields.push({
|
|
686
|
-
name,
|
|
687
|
-
goType,
|
|
688
|
-
isBoxed: false,
|
|
689
|
-
boxInfo: null,
|
|
690
|
-
wType,
|
|
691
|
-
});
|
|
692
|
-
}
|
|
663
|
+
const boxInfo = isBoxed ? this.mod.getBoxType(goType) : null;
|
|
664
|
+
envFields.push({
|
|
665
|
+
name,
|
|
666
|
+
goType,
|
|
667
|
+
isBoxed,
|
|
668
|
+
boxInfo,
|
|
669
|
+
wType: isBoxed
|
|
670
|
+
? { kind: "ref", nullable: true, typeIndex: boxInfo.typeIndex }
|
|
671
|
+
: this.toWasmType(goType),
|
|
672
|
+
});
|
|
693
673
|
}
|
|
674
|
+
return envFields;
|
|
675
|
+
}
|
|
694
676
|
|
|
677
|
+
_unpackClosureEnv() {
|
|
678
|
+
const envFields = this._buildEnvFields(this.capturedNames);
|
|
695
679
|
const envInfo = this.mod.getEnvType(envFields);
|
|
696
680
|
this.envInfo = envInfo;
|
|
697
681
|
this.envFields = envFields;
|
|
@@ -873,6 +857,21 @@ export class FunctionEmitter {
|
|
|
873
857
|
if (this.mod.structTypes.has(t.name))
|
|
874
858
|
return this.mod.structTypes.get(t.name);
|
|
875
859
|
}
|
|
860
|
+
if (t.kind === "struct" || t.kind === "StructType") {
|
|
861
|
+
const rawFields = [];
|
|
862
|
+
if (t.fields instanceof Map) {
|
|
863
|
+
for (const [k, v] of t.fields.entries())
|
|
864
|
+
rawFields.push({ name: k, goType: v });
|
|
865
|
+
} else if (Array.isArray(t.fields)) {
|
|
866
|
+
for (const f of t.fields) {
|
|
867
|
+
const names = f.names ?? (f.name ? [f.name] : []);
|
|
868
|
+
for (const n of names) rawFields.push({ name: n, goType: f.type });
|
|
869
|
+
}
|
|
870
|
+
}
|
|
871
|
+
if (rawFields.length > 0 && this.mod.getAnonStructType) {
|
|
872
|
+
return this.mod.getAnonStructType(rawFields);
|
|
873
|
+
}
|
|
874
|
+
}
|
|
876
875
|
return null;
|
|
877
876
|
}
|
|
878
877
|
|
|
@@ -930,6 +929,7 @@ export class FunctionEmitter {
|
|
|
930
929
|
return;
|
|
931
930
|
if (
|
|
932
931
|
node.kind === "CompositeLit" ||
|
|
932
|
+
node.kind === "CallExpr" ||
|
|
933
933
|
(node.kind === "UnaryExpr" && node.op === "*")
|
|
934
934
|
)
|
|
935
935
|
return;
|
|
@@ -959,6 +959,11 @@ export class FunctionEmitter {
|
|
|
959
959
|
if (recvType) {
|
|
960
960
|
let t = recvType;
|
|
961
961
|
while (t.kind === "pointer") t = t.base;
|
|
962
|
+
if (t.kind === "SelectorExpr") {
|
|
963
|
+
const pkg = t.expr?.name;
|
|
964
|
+
if (pkg) return `${pkg}.${t.field}`;
|
|
965
|
+
}
|
|
966
|
+
if (t.kind === "simd") return "simd.F32x4";
|
|
962
967
|
if (t.name) return t.name;
|
|
963
968
|
if (t.kind === "named") return t.name;
|
|
964
969
|
if (t.kind === "TypeName" || t.kind === "Ident") return t.name;
|
|
@@ -969,6 +974,10 @@ export class FunctionEmitter {
|
|
|
969
974
|
return this._getReceiverTypeName(loc.goType);
|
|
970
975
|
}
|
|
971
976
|
}
|
|
977
|
+
if (node && node.kind === "SelectorExpr") {
|
|
978
|
+
const pkg = node.expr?.name;
|
|
979
|
+
if (pkg) return `${pkg}.${node.field}`;
|
|
980
|
+
}
|
|
972
981
|
return null;
|
|
973
982
|
}
|
|
974
983
|
|
|
@@ -1082,6 +1091,18 @@ export class FunctionEmitter {
|
|
|
1082
1091
|
return defaultSize;
|
|
1083
1092
|
}
|
|
1084
1093
|
|
|
1094
|
+
_getArrayElemType(t) {
|
|
1095
|
+
if (!t) return null;
|
|
1096
|
+
if (t.elem) return t.elem;
|
|
1097
|
+
if (t.underlying?.elem) return t.underlying.elem;
|
|
1098
|
+
if (t.kind === "ArrayType") return t.elem;
|
|
1099
|
+
if (t.name && this.mod.checker?.types?.has(t.name)) {
|
|
1100
|
+
const resolved = this.mod.checker.types.get(t.name);
|
|
1101
|
+
return this._getArrayElemType(resolved);
|
|
1102
|
+
}
|
|
1103
|
+
return null;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1085
1106
|
emitZeroValue(goType, wType) {
|
|
1086
1107
|
if (wType === "i32") {
|
|
1087
1108
|
this.pushInstruction({ op: "i32.const", value: 0 });
|
|
@@ -1091,6 +1112,8 @@ export class FunctionEmitter {
|
|
|
1091
1112
|
this.pushInstruction({ op: "f32.const", value: 0.0 });
|
|
1092
1113
|
} else if (wType === "f64") {
|
|
1093
1114
|
this.pushInstruction({ op: "f64.const", value: 0.0 });
|
|
1115
|
+
} else if (wType === "v128") {
|
|
1116
|
+
this.pushInstruction({ op: "v128.const", bytes: new Array(16).fill(0) });
|
|
1094
1117
|
} else if (
|
|
1095
1118
|
typeof wType === "object" &&
|
|
1096
1119
|
wType !== null &&
|
|
@@ -1264,13 +1287,7 @@ export class FunctionEmitter {
|
|
|
1264
1287
|
}
|
|
1265
1288
|
|
|
1266
1289
|
resolveBranchDepthToOob() {
|
|
1267
|
-
|
|
1268
|
-
const ctrl = this.controlStack[i];
|
|
1269
|
-
if (ctrl.role === "oob") {
|
|
1270
|
-
return this.controlStack.length - 1 - i;
|
|
1271
|
-
}
|
|
1272
|
-
}
|
|
1273
|
-
return null;
|
|
1290
|
+
return this.resolveBranchDepthToRole("oob");
|
|
1274
1291
|
}
|
|
1275
1292
|
|
|
1276
1293
|
resolveBranchDepthToRole(targetRole) {
|
|
@@ -1360,11 +1377,25 @@ export class FunctionEmitter {
|
|
|
1360
1377
|
break;
|
|
1361
1378
|
}
|
|
1362
1379
|
}
|
|
1380
|
+
|
|
1381
|
+
_isPkgExpr(expr, pkgName) {
|
|
1382
|
+
if (expr.expr?.kind !== "Ident") return false;
|
|
1383
|
+
const name = expr.expr.name;
|
|
1384
|
+
if (pkgName !== undefined && name !== pkgName) return false;
|
|
1385
|
+
return !this.resolveLocal(name) && !this.mod.resolveGlobal(name);
|
|
1386
|
+
}
|
|
1363
1387
|
}
|
|
1364
1388
|
|
|
1365
1389
|
function copyMethods(target, source) {
|
|
1366
1390
|
const descriptors = Object.getOwnPropertyDescriptors(source.prototype);
|
|
1367
1391
|
delete descriptors.constructor;
|
|
1392
|
+
for (const key of Object.keys(descriptors)) {
|
|
1393
|
+
if (key in target.prototype) {
|
|
1394
|
+
throw new Error(
|
|
1395
|
+
`Duplicate method "${key}" found while mixing ${source.name} into ${target.name}`,
|
|
1396
|
+
);
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1368
1399
|
Object.defineProperties(target.prototype, descriptors);
|
|
1369
1400
|
}
|
|
1370
1401
|
|
|
@@ -1372,5 +1403,11 @@ copyMethods(FunctionEmitter, MapsEmitter);
|
|
|
1372
1403
|
copyMethods(FunctionEmitter, StmtsEmitter);
|
|
1373
1404
|
copyMethods(FunctionEmitter, ExprsEmitter);
|
|
1374
1405
|
copyMethods(FunctionEmitter, BuiltinsEmitter);
|
|
1375
|
-
copyMethods(FunctionEmitter,
|
|
1406
|
+
copyMethods(FunctionEmitter, StdlibCoreEmitter);
|
|
1407
|
+
copyMethods(FunctionEmitter, BytesEmitter);
|
|
1408
|
+
copyMethods(FunctionEmitter, PurePackagesEmitter);
|
|
1409
|
+
copyMethods(FunctionEmitter, IoEmitter);
|
|
1410
|
+
copyMethods(FunctionEmitter, TimeEmitter);
|
|
1411
|
+
copyMethods(FunctionEmitter, ExtendedPackagesEmitter);
|
|
1376
1412
|
copyMethods(FunctionEmitter, SharedEmitter);
|
|
1413
|
+
copyMethods(FunctionEmitter, SimdEmitter);
|
|
@@ -52,20 +52,32 @@ export function encodeI64LEB(val) {
|
|
|
52
52
|
return bytes;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
const _f32Arr = new Float32Array(1);
|
|
56
|
+
const _f32Bytes = new Uint8Array(_f32Arr.buffer);
|
|
55
57
|
export function encodeF32(val) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
return Array.from(new Uint8Array(buf));
|
|
58
|
+
_f32Arr[0] = Number(val);
|
|
59
|
+
return [_f32Bytes[0], _f32Bytes[1], _f32Bytes[2], _f32Bytes[3]];
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
const _f64Arr = new Float64Array(1);
|
|
63
|
+
const _f64Bytes = new Uint8Array(_f64Arr.buffer);
|
|
61
64
|
export function encodeF64(val) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
_f64Arr[0] = Number(val);
|
|
66
|
+
return [
|
|
67
|
+
_f64Bytes[0],
|
|
68
|
+
_f64Bytes[1],
|
|
69
|
+
_f64Bytes[2],
|
|
70
|
+
_f64Bytes[3],
|
|
71
|
+
_f64Bytes[4],
|
|
72
|
+
_f64Bytes[5],
|
|
73
|
+
_f64Bytes[6],
|
|
74
|
+
_f64Bytes[7],
|
|
75
|
+
];
|
|
65
76
|
}
|
|
66
77
|
|
|
78
|
+
const _textEncoder = new TextEncoder();
|
|
67
79
|
function encodeString(str) {
|
|
68
|
-
const utf8 =
|
|
80
|
+
const utf8 = _textEncoder.encode(str);
|
|
69
81
|
return [...encodeU32LEB(utf8.length), ...utf8];
|
|
70
82
|
}
|
|
71
83
|
|
|
@@ -381,6 +393,49 @@ const GC_OPCODES = {
|
|
|
381
393
|
"extern.convert_any": 0x1b,
|
|
382
394
|
};
|
|
383
395
|
|
|
396
|
+
// 0xFD prefixed SIMD instructions (Wasm SIMD / v128)
|
|
397
|
+
const SIMD_OPCODES = {
|
|
398
|
+
"v128.load": 0,
|
|
399
|
+
"v128.store": 11,
|
|
400
|
+
"v128.const": 12,
|
|
401
|
+
"i8x16.shuffle": 13,
|
|
402
|
+
"i8x16.swizzle": 14,
|
|
403
|
+
"i8x16.splat": 15,
|
|
404
|
+
"i16x8.splat": 16,
|
|
405
|
+
"i32x4.splat": 17,
|
|
406
|
+
"i64x2.splat": 18,
|
|
407
|
+
"f32x4.splat": 19,
|
|
408
|
+
"f64x2.splat": 20,
|
|
409
|
+
"i8x16.extract_lane_s": 21,
|
|
410
|
+
"i8x16.extract_lane_u": 22,
|
|
411
|
+
"i8x16.replace_lane": 23,
|
|
412
|
+
"i16x8.extract_lane_s": 24,
|
|
413
|
+
"i16x8.extract_lane_u": 25,
|
|
414
|
+
"i16x8.replace_lane": 26,
|
|
415
|
+
"i32x4.extract_lane": 27,
|
|
416
|
+
"i32x4.replace_lane": 28,
|
|
417
|
+
"i64x2.extract_lane": 29,
|
|
418
|
+
"i64x2.replace_lane": 30,
|
|
419
|
+
"f32x4.extract_lane": 31,
|
|
420
|
+
"f32x4.replace_lane": 32,
|
|
421
|
+
"v128.not": 77,
|
|
422
|
+
"v128.and": 78,
|
|
423
|
+
"v128.andnot": 79,
|
|
424
|
+
"v128.or": 80,
|
|
425
|
+
"v128.xor": 81,
|
|
426
|
+
"f32x4.abs": 224,
|
|
427
|
+
"f32x4.neg": 225,
|
|
428
|
+
"f32x4.sqrt": 227,
|
|
429
|
+
"f32x4.add": 228,
|
|
430
|
+
"f32x4.sub": 229,
|
|
431
|
+
"f32x4.mul": 230,
|
|
432
|
+
"f32x4.div": 231,
|
|
433
|
+
"f32x4.min": 232,
|
|
434
|
+
"f32x4.max": 233,
|
|
435
|
+
"f32x4.pmin": 234,
|
|
436
|
+
"f32x4.pmax": 235,
|
|
437
|
+
};
|
|
438
|
+
|
|
384
439
|
// Natural alignment (log2) per load/store opcode; memarg = align, offset.
|
|
385
440
|
const MEM_ALIGN = {
|
|
386
441
|
"i32.load": 2,
|
|
@@ -421,6 +476,48 @@ function encodeInstruction(inst) {
|
|
|
421
476
|
return [0xfc, ...encodeU32LEB(SAT_TRUNC_OPCODES[op])];
|
|
422
477
|
}
|
|
423
478
|
|
|
479
|
+
// 2. Check SIMD opcodes (0xFD prefix)
|
|
480
|
+
if (SIMD_OPCODES[op] !== undefined) {
|
|
481
|
+
const subOp = SIMD_OPCODES[op];
|
|
482
|
+
const bytes = [0xfd, ...encodeU32LEB(subOp)];
|
|
483
|
+
if (op === "v128.load" || op === "v128.store") {
|
|
484
|
+
bytes.push(...encodeU32LEB(inst.align ?? 2));
|
|
485
|
+
bytes.push(...encodeU32LEB(inst.offset ?? 0));
|
|
486
|
+
return bytes;
|
|
487
|
+
}
|
|
488
|
+
if (op === "v128.const") {
|
|
489
|
+
const prefixLen = bytes.length;
|
|
490
|
+
if (inst.bytes) {
|
|
491
|
+
for (let i = 0; i < 16; i++) {
|
|
492
|
+
bytes.push(inst.bytes[i] ?? 0);
|
|
493
|
+
}
|
|
494
|
+
} else if (inst.values) {
|
|
495
|
+
const vals = inst.values.slice(0, 4);
|
|
496
|
+
for (const val of vals) {
|
|
497
|
+
bytes.push(...encodeF32(val));
|
|
498
|
+
}
|
|
499
|
+
while (bytes.length < prefixLen + 16) {
|
|
500
|
+
bytes.push(0);
|
|
501
|
+
}
|
|
502
|
+
} else {
|
|
503
|
+
for (let i = 0; i < 16; i++) bytes.push(0);
|
|
504
|
+
}
|
|
505
|
+
return bytes;
|
|
506
|
+
}
|
|
507
|
+
if (op === "i8x16.shuffle") {
|
|
508
|
+
const lanes = inst.lanes ?? inst.indices ?? [];
|
|
509
|
+
for (let i = 0; i < 16; i++) {
|
|
510
|
+
bytes.push(lanes[i] ?? 0);
|
|
511
|
+
}
|
|
512
|
+
return bytes;
|
|
513
|
+
}
|
|
514
|
+
if (op.includes("extract_lane") || op.includes("replace_lane")) {
|
|
515
|
+
bytes.push((inst.lane ?? inst.index ?? 0) & 0xff);
|
|
516
|
+
return bytes;
|
|
517
|
+
}
|
|
518
|
+
return bytes;
|
|
519
|
+
}
|
|
520
|
+
|
|
424
521
|
// 2. Check WasmGC opcodes (0xFB prefix)
|
|
425
522
|
if (GC_OPCODES[op] !== undefined) {
|
|
426
523
|
const subOp = GC_OPCODES[op];
|
|
@@ -907,31 +1004,45 @@ export function encodeModule(mod) {
|
|
|
907
1004
|
const sectionOffsets = [];
|
|
908
1005
|
const codeSec = encodeCodeSection(mod.funcs, sectionOffsets);
|
|
909
1006
|
|
|
910
|
-
const
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
1007
|
+
const sections = [
|
|
1008
|
+
magic,
|
|
1009
|
+
version,
|
|
1010
|
+
GOFRONT_SECTION_BYTES,
|
|
1011
|
+
typeSec,
|
|
1012
|
+
importSec,
|
|
1013
|
+
funcSec,
|
|
1014
|
+
memorySec,
|
|
1015
|
+
tagSec,
|
|
1016
|
+
globalSec,
|
|
1017
|
+
exportSec,
|
|
1018
|
+
startSec,
|
|
1019
|
+
elemSec,
|
|
923
1020
|
];
|
|
924
|
-
|
|
1021
|
+
let totalLen = 0;
|
|
1022
|
+
for (const s of sections) totalLen += s.length;
|
|
1023
|
+
const codeStart = totalLen;
|
|
925
1024
|
mod.codeOffsets = sectionOffsets.map((o) => codeStart + o);
|
|
926
|
-
|
|
1025
|
+
totalLen += codeSec.length;
|
|
1026
|
+
let smSec = null;
|
|
927
1027
|
if (mod.sourceMappingURL) {
|
|
928
|
-
|
|
929
|
-
...
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
1028
|
+
smSec = encodeSection(0, [
|
|
1029
|
+
...encodeString("sourceMappingURL"),
|
|
1030
|
+
...encodeString(mod.sourceMappingURL),
|
|
1031
|
+
]);
|
|
1032
|
+
totalLen += smSec.length;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
const out = new Uint8Array(totalLen);
|
|
1036
|
+
let offset = 0;
|
|
1037
|
+
for (const s of sections) {
|
|
1038
|
+
out.set(s, offset);
|
|
1039
|
+
offset += s.length;
|
|
1040
|
+
}
|
|
1041
|
+
out.set(codeSec, offset);
|
|
1042
|
+
offset += codeSec.length;
|
|
1043
|
+
if (smSec) {
|
|
1044
|
+
out.set(smSec, offset);
|
|
934
1045
|
}
|
|
935
1046
|
|
|
936
|
-
return
|
|
1047
|
+
return out;
|
|
937
1048
|
}
|