gofront 1.8.0 → 1.9.1

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.
Files changed (178) hide show
  1. package/README.md +3 -3
  2. package/package.json +6 -5
  3. package/src/backend/js/expressions.js +1157 -408
  4. package/src/backend/js/index.js +327 -153
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +559 -2552
  7. package/src/backend/js/statements.js +670 -158
  8. package/src/backend/js/stdlib/index.js +45 -93
  9. package/src/backend/js/templ.js +32 -45
  10. package/src/backend/js/type-info.js +298 -19
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +91 -170
  13. package/src/backend/shared/host-unicode.js +36 -0
  14. package/src/backend/wasm/boundary.js +490 -965
  15. package/src/backend/wasm/emit-builtins.js +884 -256
  16. package/src/backend/wasm/emit-exprs.js +185 -77
  17. package/src/backend/wasm/emit-maps.js +17 -367
  18. package/src/backend/wasm/emit-shared.js +4 -1
  19. package/src/backend/wasm/emit-stmts.js +524 -240
  20. package/src/backend/wasm/emit.js +176 -38
  21. package/src/backend/wasm/globals.js +48 -8
  22. package/src/backend/wasm/glue.js +2 -4
  23. package/src/backend/wasm/index.js +44 -530
  24. package/src/backend/wasm/method-expr.js +12 -1
  25. package/src/backend/wasm/module-emitter.js +299 -770
  26. package/src/backend/wasm/monomorph.js +139 -8
  27. package/src/backend/wasm/natives.js +600 -0
  28. package/src/backend/wasm/prescan.js +5 -153
  29. package/src/backend/wasm/prune-funcs.js +89 -0
  30. package/src/backend/wasm/stdlib/index.js +2 -32
  31. package/src/backend/wasm/types.js +97 -20
  32. package/src/backend/wasm/variadic.js +9 -4
  33. package/src/cli/cli-core.js +5 -1
  34. package/src/cli/test-runner.js +115 -342
  35. package/src/compiler.js +113 -130
  36. package/src/lexer/lexer.js +106 -11
  37. package/src/lexer/templ-lexer.js +61 -18
  38. package/src/lexer/tokens.js +1 -0
  39. package/src/link/stdlib.js +355 -132
  40. package/src/link/type-names.js +204 -0
  41. package/src/link/wasm.js +30 -6
  42. package/src/lower/bounds.js +153 -0
  43. package/src/lower/captures.js +92 -33
  44. package/src/lower/embedding.js +62 -5
  45. package/src/lower/errors-as.js +196 -0
  46. package/src/lower/fmt-formatters.js +929 -0
  47. package/src/lower/functions.js +225 -7
  48. package/src/lower/gen-types.js +293 -0
  49. package/src/lower/index.js +14 -2
  50. package/src/lower/json-codecs.js +334 -245
  51. package/src/lower/ownership.js +25 -7
  52. package/src/lower/reachability.js +69 -51
  53. package/src/lower/walk.js +12 -0
  54. package/src/parser/declarations.js +30 -5
  55. package/src/parser/expressions.js +111 -57
  56. package/src/parser/statements.js +108 -0
  57. package/src/parser/templ.js +44 -5
  58. package/src/parser/types.js +12 -0
  59. package/src/resolver.js +1 -2
  60. package/src/typechecker/assignability.js +214 -19
  61. package/src/typechecker/const-fold.js +70 -27
  62. package/src/typechecker/constants.js +156 -8
  63. package/src/typechecker/expressions.js +490 -108
  64. package/src/typechecker/index.js +346 -42
  65. package/src/typechecker/init-order.js +136 -40
  66. package/src/typechecker/operand-text.js +41 -0
  67. package/src/typechecker/resolve.js +490 -65
  68. package/src/typechecker/statements.js +288 -27
  69. package/src/typechecker/stdlib/excluded.js +9 -5
  70. package/src/typechecker/stdlib/index.js +25 -9
  71. package/src/typechecker/termination.js +10 -1
  72. package/src/typechecker/types.js +287 -575
  73. package/stdlib/bytes/buffer.go +479 -0
  74. package/stdlib/bytes/bytes.go +1010 -0
  75. package/stdlib/bytes/reader.go +161 -0
  76. package/stdlib/context/context.go +115 -0
  77. package/stdlib/crypto/rand/rand.go +34 -0
  78. package/stdlib/crypto/sha256/sha256.go +249 -0
  79. package/stdlib/encoding/base64/base64.go +331 -0
  80. package/stdlib/encoding/binary/binary.go +332 -0
  81. package/stdlib/encoding/hex/hex.go +140 -0
  82. package/stdlib/encoding/json/json.go +62 -0
  83. package/stdlib/errors/errors.go +174 -0
  84. package/stdlib/fmt/errors.go +110 -0
  85. package/stdlib/fmt/format.go +732 -0
  86. package/stdlib/fmt/print.go +1232 -0
  87. package/stdlib/gom/gom.go +293 -0
  88. package/stdlib/html/html.go +251 -0
  89. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  90. package/stdlib/internal/jsonrt/dec.go +171 -38
  91. package/stdlib/internal/jsonrt/enc.go +186 -36
  92. package/stdlib/internal/jsonrt/scanner.go +17 -8
  93. package/stdlib/io/io.go +157 -1
  94. package/stdlib/maps/maps.go +131 -0
  95. package/stdlib/math/bits/bits.go +507 -0
  96. package/stdlib/math/extra.go +16 -14
  97. package/stdlib/math/math.go +439 -0
  98. package/stdlib/math/rand/rand.go +297 -0
  99. package/stdlib/os/os.go +93 -0
  100. package/stdlib/path/filepath/filepath.go +47 -0
  101. package/stdlib/path/path.go +394 -0
  102. package/stdlib/regexp/regexp.go +231 -0
  103. package/stdlib/slices/slices.go +526 -0
  104. package/stdlib/slices/sort.go +209 -0
  105. package/stdlib/slices/zsort_cmp.go +480 -0
  106. package/stdlib/slices/zsort_ordered.go +482 -0
  107. package/stdlib/sort/sort.go +391 -452
  108. package/stdlib/sort/zsort_func.go +480 -0
  109. package/stdlib/sort/zsort_iface.go +480 -0
  110. package/stdlib/strconv/float.go +1699 -0
  111. package/stdlib/strconv/isprint.go +752 -0
  112. package/stdlib/strconv/quote.go +235 -50
  113. package/stdlib/strconv/strconv.go +616 -0
  114. package/stdlib/strings/builder.go +95 -0
  115. package/stdlib/strings/reader.go +163 -0
  116. package/stdlib/strings/replacer.go +102 -0
  117. package/stdlib/strings/strings.go +807 -0
  118. package/stdlib/sync/sync.go +268 -0
  119. package/stdlib/testing/async_js.go +61 -0
  120. package/stdlib/testing/benchmark.go +297 -0
  121. package/stdlib/testing/testing.go +523 -0
  122. package/stdlib/time/duration.go +233 -0
  123. package/stdlib/time/format.go +745 -0
  124. package/stdlib/time/parse.go +790 -0
  125. package/stdlib/time/sleep_js.go +63 -0
  126. package/stdlib/time/time.go +834 -0
  127. package/stdlib/unicode/unicode.go +141 -3
  128. package/stdlib/unicode/utf8/utf8.go +464 -0
  129. package/src/backend/js/fmt-runtime.js +0 -573
  130. package/src/backend/js/stdlib/base64.js +0 -12
  131. package/src/backend/js/stdlib/binary.js +0 -102
  132. package/src/backend/js/stdlib/bits.js +0 -119
  133. package/src/backend/js/stdlib/builder.js +0 -98
  134. package/src/backend/js/stdlib/bytes.js +0 -368
  135. package/src/backend/js/stdlib/errors.js +0 -45
  136. package/src/backend/js/stdlib/fmt.js +0 -517
  137. package/src/backend/js/stdlib/gom.js +0 -155
  138. package/src/backend/js/stdlib/hex.js +0 -17
  139. package/src/backend/js/stdlib/html.js +0 -20
  140. package/src/backend/js/stdlib/io.js +0 -137
  141. package/src/backend/js/stdlib/json.js +0 -1167
  142. package/src/backend/js/stdlib/maps.js +0 -37
  143. package/src/backend/js/stdlib/math.js +0 -85
  144. package/src/backend/js/stdlib/os.js +0 -13
  145. package/src/backend/js/stdlib/path.js +0 -48
  146. package/src/backend/js/stdlib/rand.js +0 -32
  147. package/src/backend/js/stdlib/regexp.js +0 -54
  148. package/src/backend/js/stdlib/sha256.js +0 -12
  149. package/src/backend/js/stdlib/shared.js +0 -17
  150. package/src/backend/js/stdlib/simd.js +0 -34
  151. package/src/backend/js/stdlib/slices.js +0 -107
  152. package/src/backend/js/stdlib/sort.js +0 -30
  153. package/src/backend/js/stdlib/strconv.js +0 -79
  154. package/src/backend/js/stdlib/strings.js +0 -301
  155. package/src/backend/js/stdlib/sync.js +0 -13
  156. package/src/backend/js/stdlib/testing.js +0 -41
  157. package/src/backend/js/stdlib/time.js +0 -152
  158. package/src/backend/js/stdlib/unicode.js +0 -25
  159. package/src/backend/js/stdlib/utf8.js +0 -26
  160. package/src/backend/wasm/stdlib/bytes.js +0 -6716
  161. package/src/backend/wasm/stdlib/core.js +0 -10278
  162. package/src/backend/wasm/stdlib/io.js +0 -3578
  163. package/src/backend/wasm/stdlib/packages.js +0 -2402
  164. package/src/backend/wasm/stdlib/pure.js +0 -720
  165. package/src/backend/wasm/stdlib/time.js +0 -2229
  166. package/src/typechecker/stdlib/core.js +0 -1079
  167. package/src/typechecker/stdlib/extended.js +0 -1210
  168. package/stdlib/bytes/iter.go +0 -192
  169. package/stdlib/bytes/search.go +0 -240
  170. package/stdlib/bytes/split.go +0 -218
  171. package/stdlib/errors/overlay.go +0 -12
  172. package/stdlib/maps/iter.go +0 -65
  173. package/stdlib/slices/extra.go +0 -73
  174. package/stdlib/slices/iter.go +0 -113
  175. package/stdlib/strings/extra.go +0 -35
  176. package/stdlib/strings/iter.go +0 -122
  177. package/stdlib/sync/extra.go +0 -105
  178. package/stdlib/unicode/utf8/bytes.go +0 -239
@@ -1,2402 +0,0 @@
1
- // src/backend/wasm/stdlib/packages.js
2
- // FunctionEmitter mixin: sync, encoding/binary, crypto/sha256, encoding/hex, encoding/base64.
3
-
4
- import { isSliceType, toWasmType } from "../types.js";
5
-
6
- const EXT_PKG_CONSTS = {
7
- sha256: { Size: 32, BlockSize: 64 },
8
- base64: { StdPadding: 61, NoPadding: -1 },
9
- };
10
- const EXT_PKG_SPECIAL = new Set([
11
- "hex.ErrLength",
12
- "base64.StdEncoding",
13
- "base64.URLEncoding",
14
- "base64.RawStdEncoding",
15
- "base64.RawURLEncoding",
16
- "binary.LittleEndian",
17
- "binary.BigEndian",
18
- ]);
19
-
20
- export class ExtendedPackagesEmitter {
21
- _isExtendedPkgConst(expr) {
22
- if (!this._isPkgExpr(expr)) return false;
23
- const pkg = expr.expr.name;
24
- return (
25
- EXT_PKG_CONSTS[pkg]?.[expr.field] !== undefined ||
26
- EXT_PKG_SPECIAL.has(`${pkg}.${expr.field}`)
27
- );
28
- }
29
-
30
- emitExtendedPkgConst(expr, targetWasmType) {
31
- const pkg = expr.expr.name;
32
- const field = expr.field;
33
- const scalarVal = EXT_PKG_CONSTS[pkg]?.[field];
34
- if (scalarVal !== undefined) {
35
- if ((targetWasmType ?? "i64") === "i64") {
36
- this.pushInstruction({ op: "i64.const", value: BigInt(scalarVal) });
37
- } else {
38
- this.pushInstruction({ op: "i32.const", value: scalarVal });
39
- }
40
- return;
41
- }
42
- if (pkg === "hex" && field === "ErrLength") {
43
- const strIdx = this.mod.internString(
44
- "encoding/hex: odd length hex string",
45
- );
46
- this.pushInstruction({ op: "i32.const", value: strIdx });
47
- this.pushInstruction({
48
- op: "call",
49
- funcIndex: this.mod.getStringImportIndex(),
50
- });
51
- this.pushInstruction({ op: "ref.null", heapType: "any" });
52
- this.pushInstruction({
53
- op: "call",
54
- funcIndex: this.mod.resolveFuncIndex("__mk_error"),
55
- });
56
- return;
57
- }
58
- if (pkg === "base64") {
59
- const mode =
60
- field === "URLEncoding"
61
- ? 1
62
- : field === "RawStdEncoding"
63
- ? 2
64
- : field === "RawURLEncoding"
65
- ? 3
66
- : 0;
67
- const structInfo = this.mod.getStructType("base64.Encoding");
68
- this.pushInstruction({ op: "i32.const", value: mode });
69
- this.pushInstruction({
70
- op: "struct.new",
71
- typeIndex: structInfo.typeIndex,
72
- });
73
- return;
74
- }
75
- if (pkg === "binary") {
76
- const isBig = field === "BigEndian";
77
- const structInfo = this.mod.getStructType(
78
- isBig ? "binary.BigEndian" : "binary.LittleEndian",
79
- );
80
- this.pushInstruction({ op: "i32.const", value: isBig ? 1 : 0 });
81
- this.pushInstruction({
82
- op: "struct.new",
83
- typeIndex: structInfo.typeIndex,
84
- });
85
- return;
86
- }
87
- }
88
-
89
- emitSyncMutexMethodCall(method, recvExpr, _args, _targetWasmType) {
90
- const recvW = toWasmType(
91
- recvExpr._type ?? this._resolveExprGoType(recvExpr),
92
- this.mod.checker,
93
- this.mod,
94
- );
95
- this.emitExpr(recvExpr, recvW);
96
- this.pushInstruction("drop");
97
- if (method === "TryLock" || method === "TryRLock") {
98
- this.pushInstruction({ op: "i32.const", value: 1 });
99
- } else if (method === "RLocker") {
100
- this.pushInstruction({ op: "ref.null", type: "any" });
101
- }
102
- }
103
-
104
- emitSyncOnceMethodCall(method, recvExpr, args, _targetWasmType) {
105
- if (method !== "Do") return;
106
- const structInfo = this.mod.getStructType("sync.Once");
107
- const onceW = {
108
- kind: "ref",
109
- nullable: true,
110
- typeIndex: structInfo.typeIndex,
111
- };
112
- const oTmp = this.acquireTemp(onceW);
113
- this.emitExpr(recvExpr, onceW);
114
- this.pushInstruction({ op: "local.set", index: oTmp });
115
-
116
- this.pushInstruction({ op: "local.get", index: oTmp });
117
- this.pushInstruction({
118
- op: "struct.get",
119
- typeIndex: structInfo.typeIndex,
120
- fieldIndex: 0,
121
- });
122
- this.pushInstruction("i32.eqz");
123
- this.pushInstruction({ op: "if", blockType: "void" });
124
-
125
- this.pushInstruction({ op: "local.get", index: oTmp });
126
- this.pushInstruction({ op: "i32.const", value: 1 });
127
- this.pushInstruction({
128
- op: "struct.set",
129
- typeIndex: structInfo.typeIndex,
130
- fieldIndex: 0,
131
- });
132
-
133
- const fnNode = args[0];
134
- const closureGoType = this._resolveExprGoType(fnNode);
135
- const closureInfo = this.mod.getClosureType(closureGoType);
136
- const closureW = {
137
- kind: "ref",
138
- nullable: true,
139
- typeIndex: closureInfo.typeIndex,
140
- };
141
- const clTmp = this.acquireTemp(closureW);
142
- this.emitExpr(fnNode, closureW);
143
- this.pushInstruction({ op: "local.set", index: clTmp });
144
-
145
- this.pushInstruction({ op: "local.get", index: clTmp });
146
- this.pushInstruction({
147
- op: "struct.get",
148
- typeIndex: closureInfo.typeIndex,
149
- fieldIndex: 1,
150
- });
151
- this.pushInstruction({ op: "local.get", index: clTmp });
152
- this.pushInstruction({
153
- op: "struct.get",
154
- typeIndex: closureInfo.typeIndex,
155
- fieldIndex: 0,
156
- });
157
- this.pushInstruction({
158
- op: "call_ref",
159
- typeIndex: closureInfo.funcTypeIndex,
160
- });
161
-
162
- this.releaseTemp(clTmp, closureW);
163
- this.pushInstruction("end");
164
- this.releaseTemp(oTmp, onceW);
165
- }
166
-
167
- emitSyncWaitGroupMethodCall(method, recvExpr, args, _targetWasmType) {
168
- const structInfo = this.mod.getStructType("sync.WaitGroup");
169
- const wgW = {
170
- kind: "ref",
171
- nullable: true,
172
- typeIndex: structInfo.typeIndex,
173
- };
174
- const wgTmp = this.acquireTemp(wgW);
175
- this.emitExpr(recvExpr, wgW);
176
- this.pushInstruction({ op: "local.set", index: wgTmp });
177
-
178
- if (method === "Add") {
179
- const deltaTmp = this.acquireTemp("i64");
180
- this.emitExpr(args[0], "i64");
181
- this.pushInstruction({ op: "local.set", index: deltaTmp });
182
-
183
- this.pushInstruction({ op: "local.get", index: wgTmp });
184
- this.pushInstruction({ op: "local.get", index: wgTmp });
185
- this.pushInstruction({
186
- op: "struct.get",
187
- typeIndex: structInfo.typeIndex,
188
- fieldIndex: 0,
189
- });
190
- this.pushInstruction({ op: "local.get", index: deltaTmp });
191
- this.pushInstruction("i64.add");
192
- this.pushInstruction({
193
- op: "struct.set",
194
- typeIndex: structInfo.typeIndex,
195
- fieldIndex: 0,
196
- });
197
- this.releaseTemp(deltaTmp, "i64");
198
- } else if (method === "Done") {
199
- this.pushInstruction({ op: "local.get", index: wgTmp });
200
- this.pushInstruction({ op: "local.get", index: wgTmp });
201
- this.pushInstruction({
202
- op: "struct.get",
203
- typeIndex: structInfo.typeIndex,
204
- fieldIndex: 0,
205
- });
206
- this.pushInstruction({ op: "i64.const", value: 1n });
207
- this.pushInstruction("i64.sub");
208
- this.pushInstruction({
209
- op: "struct.set",
210
- typeIndex: structInfo.typeIndex,
211
- fieldIndex: 0,
212
- });
213
- }
214
- this.releaseTemp(wgTmp, wgW);
215
- }
216
-
217
- emitBinaryCall(name, call, targetWasmType) {
218
- const args = call.args;
219
- if (name === "Size") {
220
- this._emitBinarySize(args[0]);
221
- return;
222
- }
223
- if (
224
- name === "AppendUint16" ||
225
- name === "AppendUint32" ||
226
- name === "AppendUint64"
227
- ) {
228
- this.emitBinaryOrderMethodCall(
229
- "binary.LittleEndian",
230
- name,
231
- null,
232
- args,
233
- targetWasmType,
234
- );
235
- return;
236
- }
237
- if (name === "Read") {
238
- this._emitBinaryRead(args[0], args[1], args[2]);
239
- return;
240
- }
241
- if (name === "Write") {
242
- this._emitBinaryWrite(args[0], args[1], args[2]);
243
- return;
244
- }
245
- throw new Error(`Unsupported binary call: binary.${name}`);
246
- }
247
-
248
- _emitBinarySize(arg) {
249
- const t = arg._type ?? this._resolveExprGoType(arg);
250
- const sizeOf = (gt) => {
251
- if (!gt) return -1;
252
- if (gt.kind === "basic") {
253
- switch (gt.name) {
254
- case "bool":
255
- case "int8":
256
- case "uint8":
257
- case "byte":
258
- return 1;
259
- case "int16":
260
- case "uint16":
261
- return 2;
262
- case "int32":
263
- case "uint32":
264
- case "float32":
265
- case "rune":
266
- return 4;
267
- case "int64":
268
- case "uint64":
269
- case "float64":
270
- case "int":
271
- case "uint":
272
- case "uintptr":
273
- return 8;
274
- default:
275
- return -1;
276
- }
277
- }
278
- if (gt.kind === "array" || gt.kind === "ArrayType") {
279
- const es = sizeOf(gt.elem);
280
- const len = gt.len ?? gt.size ?? 0;
281
- return es > 0 ? es * len : -1;
282
- }
283
- if (
284
- gt.kind === "pointer" ||
285
- gt.kind === "PointerType" ||
286
- gt.kind === "StarExpr"
287
- ) {
288
- return sizeOf(gt.base ?? gt.expr ?? gt.operand);
289
- }
290
- if (gt.kind === "struct" || gt.kind === "StructType") {
291
- let total = 0;
292
- if (gt.fields instanceof Map) {
293
- for (const fType of gt.fields.values()) {
294
- const s = sizeOf(fType);
295
- if (s < 0) return -1;
296
- total += s;
297
- }
298
- return total;
299
- }
300
- }
301
- if (gt.name && this.mod.checker?.types?.has(gt.name)) {
302
- const resolved = this.mod.checker.types.get(gt.name);
303
- return sizeOf(resolved.underlying ?? resolved);
304
- }
305
- return -1;
306
- };
307
- const s = sizeOf(t);
308
- if (s >= 0) {
309
- this.pushInstruction({ op: "i64.const", value: BigInt(s) });
310
- } else {
311
- this.pushInstruction({ op: "i64.const", value: -1n });
312
- }
313
- }
314
-
315
- _emitBinaryRead(rExpr, orderExpr, dataExpr) {
316
- const byteGo = { kind: "basic", name: "byte" };
317
- const sliceInfo = this.mod.getSliceType(byteGo);
318
- const arrInfo = sliceInfo.arrInfo;
319
- const sliceW = {
320
- kind: "ref",
321
- nullable: true,
322
- typeIndex: sliceInfo.typeIndex,
323
- };
324
- const arrW = {
325
- kind: "ref",
326
- nullable: true,
327
- typeIndex: arrInfo.typeIndex,
328
- };
329
-
330
- // If data is a slice ([]byte): read directly into data slice
331
- const dataType = dataExpr._type ?? this._resolveExprGoType(dataExpr);
332
- if (isSliceType(dataType, this.mod.checker)) {
333
- const sTmp = this.acquireTemp(sliceW);
334
- this.emitExpr(dataExpr, sliceW);
335
- this.pushInstruction({ op: "local.set", index: sTmp });
336
-
337
- const rTmp = this.acquireTemp("anyref");
338
- this.emitExpr(rExpr, "anyref");
339
- this.pushInstruction({ op: "local.set", index: rTmp });
340
-
341
- this.pushInstruction({ op: "local.get", index: rTmp });
342
- this.pushInstruction({ op: "local.get", index: sTmp });
343
- const dispatchReadIdx = this.mod.resolveFuncIndex(
344
- "__dispatch_io.Reader_Read",
345
- );
346
- this.pushInstruction({ op: "call", funcIndex: dispatchReadIdx });
347
-
348
- // Drop n (int), return err
349
- const errTmp = this.acquireTemp("anyref");
350
- this.pushInstruction({ op: "local.set", index: errTmp });
351
- this.pushInstruction("drop"); // drop n
352
- this.pushInstruction({ op: "local.get", index: errTmp });
353
-
354
- this.releaseTemp(errTmp, "anyref");
355
- this.releaseTemp(rTmp, "anyref");
356
- this.releaseTemp(sTmp, sliceW);
357
- return;
358
- }
359
-
360
- // Scalar pointer: determine sz (1, 2, 4, 8)
361
- let sz = 4;
362
- const baseType =
363
- dataType?.base ?? dataType?.expr ?? dataType?.operand ?? dataType;
364
- if (baseType?.name === "uint16" || baseType?.name === "int16") sz = 2;
365
- else if (
366
- baseType?.name === "uint64" ||
367
- baseType?.name === "int64" ||
368
- baseType?.name === "int" ||
369
- baseType?.name === "uint" ||
370
- baseType?.name === "float64"
371
- )
372
- sz = 8;
373
- else if (
374
- baseType?.name === "byte" ||
375
- baseType?.name === "uint8" ||
376
- baseType?.name === "int8" ||
377
- baseType?.name === "bool"
378
- )
379
- sz = 1;
380
- else if (baseType?.name === "float32") sz = 4;
381
-
382
- const arrTmp = this.acquireTemp(arrW);
383
- this.pushInstruction({ op: "i32.const", value: sz });
384
- this.pushInstruction({
385
- op: "array.new_default",
386
- typeIndex: arrInfo.typeIndex,
387
- });
388
- this.pushInstruction({ op: "local.set", index: arrTmp });
389
-
390
- const bufTmp = this.acquireTemp(sliceW);
391
- this.pushInstruction({ op: "local.get", index: arrTmp });
392
- this.pushInstruction({ op: "i32.const", value: 0 });
393
- this.pushInstruction({ op: "i32.const", value: sz });
394
- this.pushInstruction({ op: "i32.const", value: sz });
395
- this.pushInstruction({
396
- op: "struct.new",
397
- typeIndex: sliceInfo.typeIndex,
398
- });
399
- this.pushInstruction({ op: "local.set", index: bufTmp });
400
-
401
- const rTmp = this.acquireTemp("anyref");
402
- this.emitExpr(rExpr, "anyref");
403
- this.pushInstruction({ op: "local.set", index: rTmp });
404
-
405
- this.pushInstruction({ op: "local.get", index: rTmp });
406
- this.pushInstruction({ op: "local.get", index: bufTmp });
407
- const dispatchReadIdx = this.mod.resolveFuncIndex(
408
- "__dispatch_io.Reader_Read",
409
- );
410
- this.pushInstruction({ op: "call", funcIndex: dispatchReadIdx });
411
-
412
- const errTmp = this.acquireTemp("anyref");
413
- const nTmp = this.acquireTemp("i64");
414
- this.pushInstruction({ op: "local.set", index: errTmp });
415
- this.pushInstruction({ op: "local.set", index: nTmp });
416
-
417
- // if err != nil -> return err
418
- this.pushInstruction({ op: "block", blockType: "anyref" });
419
- this.pushInstruction({ op: "local.get", index: errTmp });
420
- this.pushInstruction("ref.is_null");
421
- this.pushInstruction("i32.eqz");
422
- this.pushInstruction({ op: "if", blockType: "void" });
423
- this.pushInstruction({ op: "local.get", index: errTmp });
424
- this.pushInstruction({ op: "br", depth: 1 });
425
- this.pushInstruction("end");
426
-
427
- // if n < sz -> return io.EOF
428
- this.pushInstruction({ op: "local.get", index: nTmp });
429
- this.pushInstruction({ op: "i64.const", value: BigInt(sz) });
430
- this.pushInstruction("i64.lt_s");
431
- this.pushInstruction({ op: "if", blockType: "void" });
432
- this.emitIoConst("EOF", "anyref");
433
- this.pushInstruction({ op: "br", depth: 1 });
434
- this.pushInstruction("end");
435
-
436
- // Decode scalar from arrTmp and write to target
437
- const isAddressOf = dataExpr.kind === "UnaryExpr" && dataExpr.op === "&";
438
- const targetNode = isAddressOf
439
- ? (dataExpr.operand ?? dataExpr.expr)
440
- : {
441
- kind: "UnaryExpr",
442
- op: "*",
443
- operand: { ...dataExpr, _type: dataType },
444
- _type: baseType,
445
- };
446
-
447
- const isBig =
448
- orderExpr?._type?.name?.includes("BigEndian") ||
449
- orderExpr?.field === "BigEndian";
450
-
451
- let wType = "i32";
452
- if (sz === 8) {
453
- wType = baseType?.name === "float64" ? "f64" : "i64";
454
- } else if (sz === 4 && baseType?.name === "float32") {
455
- wType = "f32";
456
- }
457
-
458
- this._emitAssignToTarget(targetNode, wType, baseType, () => {
459
- if (sz === 1) {
460
- this.pushInstruction({ op: "local.get", index: arrTmp });
461
- this.pushInstruction({ op: "i32.const", value: 0 });
462
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
463
- if (baseType?.name === "int8") {
464
- this.pushInstruction("i32.extend8_s");
465
- }
466
- } else if (sz === 2) {
467
- if (isBig) {
468
- this.pushInstruction({ op: "local.get", index: arrTmp });
469
- this.pushInstruction({ op: "i32.const", value: 0 });
470
- this.pushInstruction({
471
- op: "array.get",
472
- typeIndex: arrInfo.typeIndex,
473
- });
474
- this.pushInstruction({ op: "i32.const", value: 8 });
475
- this.pushInstruction("i32.shl");
476
- this.pushInstruction({ op: "local.get", index: arrTmp });
477
- this.pushInstruction({ op: "i32.const", value: 1 });
478
- this.pushInstruction({
479
- op: "array.get",
480
- typeIndex: arrInfo.typeIndex,
481
- });
482
- this.pushInstruction("i32.or");
483
- } else {
484
- this.pushInstruction({ op: "local.get", index: arrTmp });
485
- this.pushInstruction({ op: "i32.const", value: 0 });
486
- this.pushInstruction({
487
- op: "array.get",
488
- typeIndex: arrInfo.typeIndex,
489
- });
490
- this.pushInstruction({ op: "local.get", index: arrTmp });
491
- this.pushInstruction({ op: "i32.const", value: 1 });
492
- this.pushInstruction({
493
- op: "array.get",
494
- typeIndex: arrInfo.typeIndex,
495
- });
496
- this.pushInstruction({ op: "i32.const", value: 8 });
497
- this.pushInstruction("i32.shl");
498
- this.pushInstruction("i32.or");
499
- }
500
- if (baseType?.name === "int16") {
501
- this.pushInstruction("i32.extend16_s");
502
- }
503
- } else if (sz === 4) {
504
- for (let i = 0; i < 4; i++) {
505
- this.pushInstruction({ op: "local.get", index: arrTmp });
506
- this.pushInstruction({ op: "i32.const", value: i });
507
- this.pushInstruction({
508
- op: "array.get",
509
- typeIndex: arrInfo.typeIndex,
510
- });
511
- }
512
- if (isBig) {
513
- const b3 = this.acquireTemp("i32");
514
- const b2 = this.acquireTemp("i32");
515
- const b1 = this.acquireTemp("i32");
516
- const b0 = this.acquireTemp("i32");
517
- this.pushInstruction({ op: "local.set", index: b3 });
518
- this.pushInstruction({ op: "local.set", index: b2 });
519
- this.pushInstruction({ op: "local.set", index: b1 });
520
- this.pushInstruction({ op: "local.set", index: b0 });
521
- this.pushInstruction({ op: "local.get", index: b0 });
522
- this.pushInstruction({ op: "i32.const", value: 24 });
523
- this.pushInstruction("i32.shl");
524
- this.pushInstruction({ op: "local.get", index: b1 });
525
- this.pushInstruction({ op: "i32.const", value: 16 });
526
- this.pushInstruction("i32.shl");
527
- this.pushInstruction("i32.or");
528
- this.pushInstruction({ op: "local.get", index: b2 });
529
- this.pushInstruction({ op: "i32.const", value: 8 });
530
- this.pushInstruction("i32.shl");
531
- this.pushInstruction("i32.or");
532
- this.pushInstruction({ op: "local.get", index: b3 });
533
- this.pushInstruction("i32.or");
534
- this.releaseTemp(b0, "i32");
535
- this.releaseTemp(b1, "i32");
536
- this.releaseTemp(b2, "i32");
537
- this.releaseTemp(b3, "i32");
538
- } else {
539
- const b3 = this.acquireTemp("i32");
540
- const b2 = this.acquireTemp("i32");
541
- const b1 = this.acquireTemp("i32");
542
- const b0 = this.acquireTemp("i32");
543
- this.pushInstruction({ op: "local.set", index: b3 });
544
- this.pushInstruction({ op: "local.set", index: b2 });
545
- this.pushInstruction({ op: "local.set", index: b1 });
546
- this.pushInstruction({ op: "local.set", index: b0 });
547
- this.pushInstruction({ op: "local.get", index: b0 });
548
- this.pushInstruction({ op: "local.get", index: b1 });
549
- this.pushInstruction({ op: "i32.const", value: 8 });
550
- this.pushInstruction("i32.shl");
551
- this.pushInstruction("i32.or");
552
- this.pushInstruction({ op: "local.get", index: b2 });
553
- this.pushInstruction({ op: "i32.const", value: 16 });
554
- this.pushInstruction("i32.shl");
555
- this.pushInstruction("i32.or");
556
- this.pushInstruction({ op: "local.get", index: b3 });
557
- this.pushInstruction({ op: "i32.const", value: 24 });
558
- this.pushInstruction("i32.shl");
559
- this.pushInstruction("i32.or");
560
- this.releaseTemp(b0, "i32");
561
- this.releaseTemp(b1, "i32");
562
- this.releaseTemp(b2, "i32");
563
- this.releaseTemp(b3, "i32");
564
- }
565
- if (baseType?.name === "float32") {
566
- this.pushInstruction("f32.reinterpret_i32");
567
- }
568
- } else if (sz === 8) {
569
- const bTmps = [];
570
- for (let i = 0; i < 8; i++) {
571
- this.pushInstruction({ op: "local.get", index: arrTmp });
572
- this.pushInstruction({ op: "i32.const", value: i });
573
- this.pushInstruction({
574
- op: "array.get",
575
- typeIndex: arrInfo.typeIndex,
576
- });
577
- this.pushInstruction("i64.extend_i32_u");
578
- const bt = this.acquireTemp("i64");
579
- this.pushInstruction({ op: "local.set", index: bt });
580
- bTmps.push(bt);
581
- }
582
- this.pushInstruction({ op: "i64.const", value: 0n });
583
- for (let i = 0; i < 8; i++) {
584
- const shift = isBig ? (7 - i) * 8 : i * 8;
585
- this.pushInstruction({ op: "local.get", index: bTmps[i] });
586
- if (shift > 0) {
587
- this.pushInstruction({ op: "i64.const", value: BigInt(shift) });
588
- this.pushInstruction("i64.shl");
589
- }
590
- this.pushInstruction("i64.or");
591
- }
592
- for (const bt of bTmps) this.releaseTemp(bt, "i64");
593
- if (baseType?.name === "float64") {
594
- this.pushInstruction("f64.reinterpret_i64");
595
- }
596
- }
597
- });
598
-
599
- // return nil error
600
- this.pushInstruction({ op: "ref.null", heapType: "any" });
601
- this.pushInstruction("end"); // end block
602
-
603
- this.releaseTemp(nTmp, "i64");
604
- this.releaseTemp(errTmp, "anyref");
605
- this.releaseTemp(rTmp, "anyref");
606
- this.releaseTemp(bufTmp, sliceW);
607
- this.releaseTemp(arrTmp, arrW);
608
- }
609
-
610
- _emitBinaryWrite(wExpr, orderExpr, dataExpr) {
611
- const byteGo = { kind: "basic", name: "byte" };
612
- const sliceInfo = this.mod.getSliceType(byteGo);
613
- const arrInfo = sliceInfo.arrInfo;
614
- const sliceW = {
615
- kind: "ref",
616
- nullable: true,
617
- typeIndex: sliceInfo.typeIndex,
618
- };
619
- const arrW = {
620
- kind: "ref",
621
- nullable: true,
622
- typeIndex: arrInfo.typeIndex,
623
- };
624
-
625
- const dataType = dataExpr._type ?? this._resolveExprGoType(dataExpr);
626
- if (isSliceType(dataType, this.mod.checker)) {
627
- const sTmp = this.acquireTemp(sliceW);
628
- this.emitExpr(dataExpr, sliceW);
629
- this.pushInstruction({ op: "local.set", index: sTmp });
630
-
631
- const wTmp = this.acquireTemp("anyref");
632
- this.emitExpr(wExpr, "anyref");
633
- this.pushInstruction({ op: "local.set", index: wTmp });
634
-
635
- this.pushInstruction({ op: "local.get", index: wTmp });
636
- this.pushInstruction({ op: "local.get", index: sTmp });
637
- const dispatchWriteIdx = this.mod.resolveFuncIndex(
638
- "__dispatch_io.Writer_Write",
639
- );
640
- this.pushInstruction({ op: "call", funcIndex: dispatchWriteIdx });
641
-
642
- const errTmp = this.acquireTemp("anyref");
643
- this.pushInstruction({ op: "local.set", index: errTmp });
644
- this.pushInstruction("drop"); // drop n
645
- this.pushInstruction({ op: "local.get", index: errTmp });
646
-
647
- this.releaseTemp(errTmp, "anyref");
648
- this.releaseTemp(wTmp, "anyref");
649
- this.releaseTemp(sTmp, sliceW);
650
- return;
651
- }
652
-
653
- let sz = 4;
654
- if (dataType?.name === "uint16" || dataType?.name === "int16") sz = 2;
655
- else if (
656
- dataType?.name === "uint64" ||
657
- dataType?.name === "int64" ||
658
- dataType?.name === "int" ||
659
- dataType?.name === "uint" ||
660
- dataType?.name === "float64"
661
- )
662
- sz = 8;
663
- else if (
664
- dataType?.name === "byte" ||
665
- dataType?.name === "uint8" ||
666
- dataType?.name === "int8" ||
667
- dataType?.name === "bool"
668
- )
669
- sz = 1;
670
- else if (dataType?.name === "float32") sz = 4;
671
-
672
- const isBig =
673
- orderExpr?._type?.name?.includes("BigEndian") ||
674
- orderExpr?.field === "BigEndian";
675
-
676
- const arrTmp = this.acquireTemp(arrW);
677
- this.pushInstruction({ op: "i32.const", value: sz });
678
- this.pushInstruction({
679
- op: "array.new_default",
680
- typeIndex: arrInfo.typeIndex,
681
- });
682
- this.pushInstruction({ op: "local.set", index: arrTmp });
683
-
684
- if (sz === 1) {
685
- const vTmp = this.acquireTemp("i32");
686
- this.emitExpr(dataExpr, "i32");
687
- this.pushInstruction({ op: "local.set", index: vTmp });
688
-
689
- this.pushInstruction({ op: "local.get", index: arrTmp });
690
- this.pushInstruction({ op: "i32.const", value: 0 });
691
- this.pushInstruction({ op: "local.get", index: vTmp });
692
- this.pushInstruction({ op: "i32.const", value: 0xff });
693
- this.pushInstruction("i32.and");
694
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
695
- this.releaseTemp(vTmp, "i32");
696
- } else if (sz === 2) {
697
- const vTmp = this.acquireTemp("i32");
698
- this.emitExpr(dataExpr, "i32");
699
- this.pushInstruction({ op: "local.set", index: vTmp });
700
-
701
- // byte 0
702
- this.pushInstruction({ op: "local.get", index: arrTmp });
703
- this.pushInstruction({ op: "i32.const", value: 0 });
704
- this.pushInstruction({ op: "local.get", index: vTmp });
705
- if (isBig) {
706
- this.pushInstruction({ op: "i32.const", value: 8 });
707
- this.pushInstruction("i32.shr_u");
708
- }
709
- this.pushInstruction({ op: "i32.const", value: 0xff });
710
- this.pushInstruction("i32.and");
711
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
712
-
713
- // byte 1
714
- this.pushInstruction({ op: "local.get", index: arrTmp });
715
- this.pushInstruction({ op: "i32.const", value: 1 });
716
- this.pushInstruction({ op: "local.get", index: vTmp });
717
- if (!isBig) {
718
- this.pushInstruction({ op: "i32.const", value: 8 });
719
- this.pushInstruction("i32.shr_u");
720
- }
721
- this.pushInstruction({ op: "i32.const", value: 0xff });
722
- this.pushInstruction("i32.and");
723
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
724
- this.releaseTemp(vTmp, "i32");
725
- } else if (sz === 4) {
726
- const vTmp = this.acquireTemp("i32");
727
- if (dataType?.name === "float32") {
728
- this.emitExpr(dataExpr, "f32");
729
- this.pushInstruction("i32.reinterpret_f32");
730
- } else {
731
- this.emitExpr(dataExpr, "i32");
732
- }
733
- this.pushInstruction({ op: "local.set", index: vTmp });
734
-
735
- for (let i = 0; i < 4; i++) {
736
- const shift = isBig ? (3 - i) * 8 : i * 8;
737
- this.pushInstruction({ op: "local.get", index: arrTmp });
738
- this.pushInstruction({ op: "i32.const", value: i });
739
- this.pushInstruction({ op: "local.get", index: vTmp });
740
- if (shift > 0) {
741
- this.pushInstruction({ op: "i32.const", value: shift });
742
- this.pushInstruction("i32.shr_u");
743
- }
744
- this.pushInstruction({ op: "i32.const", value: 0xff });
745
- this.pushInstruction("i32.and");
746
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
747
- }
748
- this.releaseTemp(vTmp, "i32");
749
- } else if (sz === 8) {
750
- const vTmp = this.acquireTemp("i64");
751
- if (dataType?.name === "float64") {
752
- this.emitExpr(dataExpr, "f64");
753
- this.pushInstruction("i64.reinterpret_f64");
754
- } else {
755
- this.emitExpr(dataExpr, "i64");
756
- }
757
- this.pushInstruction({ op: "local.set", index: vTmp });
758
-
759
- for (let i = 0; i < 8; i++) {
760
- const shift = isBig ? (7 - i) * 8 : i * 8;
761
- this.pushInstruction({ op: "local.get", index: arrTmp });
762
- this.pushInstruction({ op: "i32.const", value: i });
763
- this.pushInstruction({ op: "local.get", index: vTmp });
764
- if (shift > 0) {
765
- this.pushInstruction({ op: "i64.const", value: BigInt(shift) });
766
- this.pushInstruction("i64.shr_u");
767
- }
768
- this.pushInstruction("i32.wrap_i64");
769
- this.pushInstruction({ op: "i32.const", value: 0xff });
770
- this.pushInstruction("i32.and");
771
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
772
- }
773
- this.releaseTemp(vTmp, "i64");
774
- }
775
-
776
- const bufTmp = this.acquireTemp(sliceW);
777
- this.pushInstruction({ op: "local.get", index: arrTmp });
778
- this.pushInstruction({ op: "i32.const", value: 0 });
779
- this.pushInstruction({ op: "i32.const", value: sz });
780
- this.pushInstruction({ op: "i32.const", value: sz });
781
- this.pushInstruction({
782
- op: "struct.new",
783
- typeIndex: sliceInfo.typeIndex,
784
- });
785
- this.pushInstruction({ op: "local.set", index: bufTmp });
786
-
787
- const wTmp = this.acquireTemp("anyref");
788
- this.emitExpr(wExpr, "anyref");
789
- this.pushInstruction({ op: "local.set", index: wTmp });
790
-
791
- this.pushInstruction({ op: "local.get", index: wTmp });
792
- this.pushInstruction({ op: "local.get", index: bufTmp });
793
- const dispatchWriteIdx = this.mod.resolveFuncIndex(
794
- "__dispatch_io.Writer_Write",
795
- );
796
- this.pushInstruction({ op: "call", funcIndex: dispatchWriteIdx });
797
-
798
- const errTmp = this.acquireTemp("anyref");
799
- this.pushInstruction({ op: "local.set", index: errTmp });
800
- this.pushInstruction("drop"); // drop n
801
- this.pushInstruction({ op: "local.get", index: errTmp });
802
-
803
- this.releaseTemp(errTmp, "anyref");
804
- this.releaseTemp(wTmp, "anyref");
805
- this.releaseTemp(bufTmp, sliceW);
806
- this.releaseTemp(arrTmp, arrW);
807
- }
808
-
809
- emitBinaryOrderMethodCall(
810
- recvTypeName,
811
- method,
812
- recvExpr,
813
- args,
814
- targetWasmType,
815
- ) {
816
- const isBig =
817
- recvTypeName?.includes("BigEndian") ||
818
- recvExpr?.field === "BigEndian" ||
819
- false;
820
-
821
- const byteGo = { kind: "basic", name: "byte" };
822
- const sliceInfo = this.mod.getSliceType(byteGo);
823
- const arrInfo = sliceInfo.arrInfo;
824
- const sliceW = {
825
- kind: "ref",
826
- nullable: true,
827
- typeIndex: sliceInfo.typeIndex,
828
- };
829
- const arrW = {
830
- kind: "ref",
831
- nullable: true,
832
- typeIndex: arrInfo.typeIndex,
833
- };
834
-
835
- if (method === "String") {
836
- const strIdx = this.mod.internString(
837
- isBig ? "BigEndian" : "LittleEndian",
838
- );
839
- this.pushInstruction({ op: "i32.const", value: strIdx });
840
- this.pushInstruction({
841
- op: "call",
842
- funcIndex: this.mod.getStringImportIndex(),
843
- });
844
- return;
845
- }
846
-
847
- if (method === "Uint16") {
848
- const sTmp = this.acquireTemp(sliceW);
849
- this.emitExpr(args[0], sliceW);
850
- this.pushInstruction({ op: "local.set", index: sTmp });
851
-
852
- const arrTmp = this.acquireTemp(arrW);
853
- const offTmp = this.acquireTemp("i32");
854
- const lenTmp = this.acquireTemp("i32");
855
- this._emitSliceUnpack(sTmp, sliceInfo, {
856
- arr: arrTmp,
857
- off: offTmp,
858
- len: lenTmp,
859
- });
860
-
861
- this.pushInstruction({ op: "local.get", index: arrTmp });
862
- this.pushInstruction({ op: "local.get", index: offTmp });
863
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
864
-
865
- this.pushInstruction({ op: "local.get", index: arrTmp });
866
- this.pushInstruction({ op: "local.get", index: offTmp });
867
- this.pushInstruction({ op: "i32.const", value: 1 });
868
- this.pushInstruction("i32.add");
869
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
870
-
871
- if (isBig) {
872
- // (b0 << 8) | b1
873
- this.pushInstruction({ op: "local.set", index: lenTmp }); // b1
874
- this.pushInstruction({ op: "i32.const", value: 8 });
875
- this.pushInstruction("i32.shl"); // b0 << 8
876
- this.pushInstruction({ op: "local.get", index: lenTmp });
877
- this.pushInstruction("i32.or");
878
- } else {
879
- // b0 | (b1 << 8)
880
- this.pushInstruction({ op: "i32.const", value: 8 });
881
- this.pushInstruction("i32.shl");
882
- this.pushInstruction("i32.or");
883
- }
884
-
885
- if ((targetWasmType ?? "i32") === "i64") {
886
- this.pushInstruction("i64.extend_i32_u");
887
- }
888
- this.releaseTemp(lenTmp, "i32");
889
- this.releaseTemp(offTmp, "i32");
890
- this.releaseTemp(arrTmp, arrW);
891
- this.releaseTemp(sTmp, sliceW);
892
- return;
893
- }
894
-
895
- if (method === "Uint32") {
896
- const sTmp = this.acquireTemp(sliceW);
897
- this.emitExpr(args[0], sliceW);
898
- this.pushInstruction({ op: "local.set", index: sTmp });
899
-
900
- const arrTmp = this.acquireTemp(arrW);
901
- const offTmp = this.acquireTemp("i32");
902
- this._emitSliceUnpack(sTmp, sliceInfo, { arr: arrTmp, off: offTmp });
903
-
904
- const bTmps = [];
905
- for (let i = 0; i < 4; i++) {
906
- this.pushInstruction({ op: "local.get", index: arrTmp });
907
- this.pushInstruction({ op: "local.get", index: offTmp });
908
- if (i > 0) {
909
- this.pushInstruction({ op: "i32.const", value: i });
910
- this.pushInstruction("i32.add");
911
- }
912
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
913
- const bt = this.acquireTemp("i32");
914
- this.pushInstruction({ op: "local.set", index: bt });
915
- bTmps.push(bt);
916
- }
917
-
918
- this.pushInstruction({ op: "i32.const", value: 0 });
919
- for (let i = 0; i < 4; i++) {
920
- const shift = isBig ? (3 - i) * 8 : i * 8;
921
- this.pushInstruction({ op: "local.get", index: bTmps[i] });
922
- if (shift > 0) {
923
- this.pushInstruction({ op: "i32.const", value: shift });
924
- this.pushInstruction("i32.shl");
925
- }
926
- this.pushInstruction("i32.or");
927
- }
928
- for (const bt of bTmps) this.releaseTemp(bt, "i32");
929
-
930
- if ((targetWasmType ?? "i32") === "i64") {
931
- this.pushInstruction("i64.extend_i32_u");
932
- }
933
- this.releaseTemp(offTmp, "i32");
934
- this.releaseTemp(arrTmp, arrW);
935
- this.releaseTemp(sTmp, sliceW);
936
- return;
937
- }
938
-
939
- if (method === "Uint64") {
940
- const sTmp = this.acquireTemp(sliceW);
941
- this.emitExpr(args[0], sliceW);
942
- this.pushInstruction({ op: "local.set", index: sTmp });
943
-
944
- const arrTmp = this.acquireTemp(arrW);
945
- const offTmp = this.acquireTemp("i32");
946
- this._emitSliceUnpack(sTmp, sliceInfo, { arr: arrTmp, off: offTmp });
947
-
948
- const bTmps = [];
949
- for (let i = 0; i < 8; i++) {
950
- this.pushInstruction({ op: "local.get", index: arrTmp });
951
- this.pushInstruction({ op: "local.get", index: offTmp });
952
- if (i > 0) {
953
- this.pushInstruction({ op: "i32.const", value: i });
954
- this.pushInstruction("i32.add");
955
- }
956
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
957
- this.pushInstruction("i64.extend_i32_u");
958
- const bt = this.acquireTemp("i64");
959
- this.pushInstruction({ op: "local.set", index: bt });
960
- bTmps.push(bt);
961
- }
962
-
963
- this.pushInstruction({ op: "i64.const", value: 0n });
964
- for (let i = 0; i < 8; i++) {
965
- const shift = isBig ? (7 - i) * 8 : i * 8;
966
- this.pushInstruction({ op: "local.get", index: bTmps[i] });
967
- if (shift > 0) {
968
- this.pushInstruction({ op: "i64.const", value: BigInt(shift) });
969
- this.pushInstruction("i64.shl");
970
- }
971
- this.pushInstruction("i64.or");
972
- }
973
- for (const bt of bTmps) this.releaseTemp(bt, "i64");
974
-
975
- this.releaseTemp(offTmp, "i32");
976
- this.releaseTemp(arrTmp, arrW);
977
- this.releaseTemp(sTmp, sliceW);
978
- return;
979
- }
980
-
981
- if (method === "PutUint16") {
982
- const sTmp = this.acquireTemp(sliceW);
983
- this.emitExpr(args[0], sliceW);
984
- this.pushInstruction({ op: "local.set", index: sTmp });
985
-
986
- const vTmp = this.acquireTemp("i32");
987
- this.emitExpr(args[1], "i32");
988
- this.pushInstruction({ op: "local.set", index: vTmp });
989
-
990
- const arrTmp = this.acquireTemp(arrW);
991
- const offTmp = this.acquireTemp("i32");
992
- this._emitSliceUnpack(sTmp, sliceInfo, { arr: arrTmp, off: offTmp });
993
-
994
- // b[0]
995
- this.pushInstruction({ op: "local.get", index: arrTmp });
996
- this.pushInstruction({ op: "local.get", index: offTmp });
997
- this.pushInstruction({ op: "local.get", index: vTmp });
998
- if (isBig) {
999
- this.pushInstruction({ op: "i32.const", value: 8 });
1000
- this.pushInstruction("i32.shr_u");
1001
- }
1002
- this.pushInstruction({ op: "i32.const", value: 0xff });
1003
- this.pushInstruction("i32.and");
1004
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
1005
-
1006
- // b[1]
1007
- this.pushInstruction({ op: "local.get", index: arrTmp });
1008
- this.pushInstruction({ op: "local.get", index: offTmp });
1009
- this.pushInstruction({ op: "i32.const", value: 1 });
1010
- this.pushInstruction("i32.add");
1011
- this.pushInstruction({ op: "local.get", index: vTmp });
1012
- if (!isBig) {
1013
- this.pushInstruction({ op: "i32.const", value: 8 });
1014
- this.pushInstruction("i32.shr_u");
1015
- }
1016
- this.pushInstruction({ op: "i32.const", value: 0xff });
1017
- this.pushInstruction("i32.and");
1018
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
1019
-
1020
- this.releaseTemp(offTmp, "i32");
1021
- this.releaseTemp(arrTmp, arrW);
1022
- this.releaseTemp(vTmp, "i32");
1023
- this.releaseTemp(sTmp, sliceW);
1024
- return;
1025
- }
1026
-
1027
- if (method === "PutUint32") {
1028
- const sTmp = this.acquireTemp(sliceW);
1029
- this.emitExpr(args[0], sliceW);
1030
- this.pushInstruction({ op: "local.set", index: sTmp });
1031
-
1032
- const vTmp = this.acquireTemp("i32");
1033
- this.emitExpr(args[1], "i32");
1034
- this.pushInstruction({ op: "local.set", index: vTmp });
1035
-
1036
- const arrTmp = this.acquireTemp(arrW);
1037
- const offTmp = this.acquireTemp("i32");
1038
- this._emitSliceUnpack(sTmp, sliceInfo, { arr: arrTmp, off: offTmp });
1039
-
1040
- for (let i = 0; i < 4; i++) {
1041
- const shift = isBig ? (3 - i) * 8 : i * 8;
1042
- this.pushInstruction({ op: "local.get", index: arrTmp });
1043
- this.pushInstruction({ op: "local.get", index: offTmp });
1044
- if (i > 0) {
1045
- this.pushInstruction({ op: "i32.const", value: i });
1046
- this.pushInstruction("i32.add");
1047
- }
1048
- this.pushInstruction({ op: "local.get", index: vTmp });
1049
- if (shift > 0) {
1050
- this.pushInstruction({ op: "i32.const", value: shift });
1051
- this.pushInstruction("i32.shr_u");
1052
- }
1053
- this.pushInstruction({ op: "i32.const", value: 0xff });
1054
- this.pushInstruction("i32.and");
1055
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
1056
- }
1057
-
1058
- this.releaseTemp(offTmp, "i32");
1059
- this.releaseTemp(arrTmp, arrW);
1060
- this.releaseTemp(vTmp, "i32");
1061
- this.releaseTemp(sTmp, sliceW);
1062
- return;
1063
- }
1064
-
1065
- if (method === "PutUint64") {
1066
- const sTmp = this.acquireTemp(sliceW);
1067
- this.emitExpr(args[0], sliceW);
1068
- this.pushInstruction({ op: "local.set", index: sTmp });
1069
-
1070
- const vTmp = this.acquireTemp("i64");
1071
- this.emitExpr(args[1], "i64");
1072
- this.pushInstruction({ op: "local.set", index: vTmp });
1073
-
1074
- const arrTmp = this.acquireTemp(arrW);
1075
- const offTmp = this.acquireTemp("i32");
1076
- this._emitSliceUnpack(sTmp, sliceInfo, { arr: arrTmp, off: offTmp });
1077
-
1078
- for (let i = 0; i < 8; i++) {
1079
- const shift = isBig ? (7 - i) * 8 : i * 8;
1080
- this.pushInstruction({ op: "local.get", index: arrTmp });
1081
- this.pushInstruction({ op: "local.get", index: offTmp });
1082
- if (i > 0) {
1083
- this.pushInstruction({ op: "i32.const", value: i });
1084
- this.pushInstruction("i32.add");
1085
- }
1086
- this.pushInstruction({ op: "local.get", index: vTmp });
1087
- if (shift > 0) {
1088
- this.pushInstruction({ op: "i64.const", value: BigInt(shift) });
1089
- this.pushInstruction("i64.shr_u");
1090
- }
1091
- this.pushInstruction("i32.wrap_i64");
1092
- this.pushInstruction({ op: "i32.const", value: 0xff });
1093
- this.pushInstruction("i32.and");
1094
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
1095
- }
1096
-
1097
- this.releaseTemp(offTmp, "i32");
1098
- this.releaseTemp(arrTmp, arrW);
1099
- this.releaseTemp(vTmp, "i64");
1100
- this.releaseTemp(sTmp, sliceW);
1101
- return;
1102
- }
1103
-
1104
- if (
1105
- method === "AppendUint16" ||
1106
- method === "AppendUint32" ||
1107
- method === "AppendUint64"
1108
- ) {
1109
- const byteCount =
1110
- method === "AppendUint16" ? 2 : method === "AppendUint32" ? 4 : 8;
1111
- const sNode = args[0];
1112
- const sTmp = this.acquireTemp(sliceW);
1113
- this.emitExpr(sNode, sliceW);
1114
- this.pushInstruction({ op: "local.set", index: sTmp });
1115
-
1116
- const oldArrTmp = this.acquireTemp(arrW);
1117
- const oldOffTmp = this.acquireTemp("i32");
1118
- const oldLenTmp = this.acquireTemp("i32");
1119
- const oldCapTmp = this.acquireTemp("i32");
1120
- this._emitSliceUnpack(sTmp, sliceInfo, {
1121
- arr: oldArrTmp,
1122
- off: oldOffTmp,
1123
- len: oldLenTmp,
1124
- cap: oldCapTmp,
1125
- });
1126
- this.releaseTemp(sTmp, sliceW);
1127
-
1128
- const newArrTmp = this.acquireTemp(arrW);
1129
- const newOffTmp = this.acquireTemp("i32");
1130
- const newCapTmp = this.acquireTemp("i32");
1131
- const newLenTmp = this.acquireTemp("i32");
1132
-
1133
- this.pushInstruction({ op: "local.get", index: oldLenTmp });
1134
- this.pushInstruction({ op: "i32.const", value: byteCount });
1135
- this.pushInstruction("i32.add");
1136
- this.pushInstruction({ op: "local.set", index: newLenTmp });
1137
-
1138
- this._emitGrowSlice({
1139
- arrInfo,
1140
- elemGoType: byteGo,
1141
- oldArrTmp,
1142
- oldOffTmp,
1143
- oldLenTmp,
1144
- oldCapTmp,
1145
- newArrTmp,
1146
- newOffTmp,
1147
- newLenTmp,
1148
- newCapTmp,
1149
- });
1150
-
1151
- if (byteCount === 2) {
1152
- const vTmp = this.acquireTemp("i32");
1153
- this.emitExpr(args[1], "i32");
1154
- this.pushInstruction({ op: "local.set", index: vTmp });
1155
-
1156
- for (let i = 0; i < 2; i++) {
1157
- const shift = isBig ? (1 - i) * 8 : i * 8;
1158
- this.pushInstruction({ op: "local.get", index: newArrTmp });
1159
- this.pushInstruction({ op: "local.get", index: newOffTmp });
1160
- this.pushInstruction({ op: "local.get", index: oldLenTmp });
1161
- this.pushInstruction("i32.add");
1162
- if (i > 0) {
1163
- this.pushInstruction({ op: "i32.const", value: i });
1164
- this.pushInstruction("i32.add");
1165
- }
1166
- this.pushInstruction({ op: "local.get", index: vTmp });
1167
- if (shift > 0) {
1168
- this.pushInstruction({ op: "i32.const", value: shift });
1169
- this.pushInstruction("i32.shr_u");
1170
- }
1171
- this.pushInstruction({ op: "i32.const", value: 0xff });
1172
- this.pushInstruction("i32.and");
1173
- this.pushInstruction({
1174
- op: "array.set",
1175
- typeIndex: arrInfo.typeIndex,
1176
- });
1177
- }
1178
- this.releaseTemp(vTmp, "i32");
1179
- } else if (byteCount === 4) {
1180
- const vTmp = this.acquireTemp("i32");
1181
- this.emitExpr(args[1], "i32");
1182
- this.pushInstruction({ op: "local.set", index: vTmp });
1183
-
1184
- for (let i = 0; i < 4; i++) {
1185
- const shift = isBig ? (3 - i) * 8 : i * 8;
1186
- this.pushInstruction({ op: "local.get", index: newArrTmp });
1187
- this.pushInstruction({ op: "local.get", index: newOffTmp });
1188
- this.pushInstruction({ op: "local.get", index: oldLenTmp });
1189
- this.pushInstruction("i32.add");
1190
- if (i > 0) {
1191
- this.pushInstruction({ op: "i32.const", value: i });
1192
- this.pushInstruction("i32.add");
1193
- }
1194
- this.pushInstruction({ op: "local.get", index: vTmp });
1195
- if (shift > 0) {
1196
- this.pushInstruction({ op: "i32.const", value: shift });
1197
- this.pushInstruction("i32.shr_u");
1198
- }
1199
- this.pushInstruction({ op: "i32.const", value: 0xff });
1200
- this.pushInstruction("i32.and");
1201
- this.pushInstruction({
1202
- op: "array.set",
1203
- typeIndex: arrInfo.typeIndex,
1204
- });
1205
- }
1206
- this.releaseTemp(vTmp, "i32");
1207
- } else {
1208
- const vTmp = this.acquireTemp("i64");
1209
- this.emitExpr(args[1], "i64");
1210
- this.pushInstruction({ op: "local.set", index: vTmp });
1211
-
1212
- for (let i = 0; i < 8; i++) {
1213
- const shift = isBig ? (7 - i) * 8 : i * 8;
1214
- this.pushInstruction({ op: "local.get", index: newArrTmp });
1215
- this.pushInstruction({ op: "local.get", index: newOffTmp });
1216
- this.pushInstruction({ op: "local.get", index: oldLenTmp });
1217
- this.pushInstruction("i32.add");
1218
- if (i > 0) {
1219
- this.pushInstruction({ op: "i32.const", value: i });
1220
- this.pushInstruction("i32.add");
1221
- }
1222
- this.pushInstruction({ op: "local.get", index: vTmp });
1223
- if (shift > 0) {
1224
- this.pushInstruction({ op: "i64.const", value: BigInt(shift) });
1225
- this.pushInstruction("i64.shr_u");
1226
- }
1227
- this.pushInstruction("i32.wrap_i64");
1228
- this.pushInstruction({ op: "i32.const", value: 0xff });
1229
- this.pushInstruction("i32.and");
1230
- this.pushInstruction({
1231
- op: "array.set",
1232
- typeIndex: arrInfo.typeIndex,
1233
- });
1234
- }
1235
- this.releaseTemp(vTmp, "i64");
1236
- }
1237
-
1238
- this.pushInstruction({ op: "local.get", index: newArrTmp });
1239
- this.pushInstruction({ op: "local.get", index: newOffTmp });
1240
- this.pushInstruction({ op: "local.get", index: newLenTmp });
1241
- this.pushInstruction({ op: "local.get", index: newCapTmp });
1242
- this.pushInstruction({
1243
- op: "struct.new",
1244
- typeIndex: sliceInfo.typeIndex,
1245
- });
1246
-
1247
- this.releaseTemp(newCapTmp, "i32");
1248
- this.releaseTemp(newLenTmp, "i32");
1249
- this.releaseTemp(newOffTmp, "i32");
1250
- this.releaseTemp(newArrTmp, arrW);
1251
- this.releaseTemp(oldCapTmp, "i32");
1252
- this.releaseTemp(oldLenTmp, "i32");
1253
- this.releaseTemp(oldOffTmp, "i32");
1254
- this.releaseTemp(oldArrTmp, arrW);
1255
- return;
1256
- }
1257
-
1258
- throw new Error(`Unsupported binary method: ${method}`);
1259
- }
1260
-
1261
- emitSha256Call(name, call, _targetWasmType) {
1262
- const args = call.args;
1263
- if (name === "Sum256") {
1264
- const byteGo = { kind: "basic", name: "byte" };
1265
- const sliceInfo = this.mod.getSliceType(byteGo);
1266
- const arrInfo = sliceInfo.arrInfo;
1267
- const sliceW = {
1268
- kind: "ref",
1269
- nullable: true,
1270
- typeIndex: sliceInfo.typeIndex,
1271
- };
1272
- const arrW = {
1273
- kind: "ref",
1274
- nullable: true,
1275
- typeIndex: arrInfo.typeIndex,
1276
- };
1277
-
1278
- const sTmp = this.acquireTemp(sliceW);
1279
- this.emitExpr(args[0], sliceW);
1280
- this.pushInstruction({ op: "local.set", index: sTmp });
1281
-
1282
- const arrTmp = this.acquireTemp(arrW);
1283
- const offTmp = this.acquireTemp("i32");
1284
- const lenTmp = this.acquireTemp("i32");
1285
- this._emitSliceUnpack(sTmp, sliceInfo, {
1286
- arr: arrTmp,
1287
- off: offTmp,
1288
- len: lenTmp,
1289
- });
1290
-
1291
- // raw_bytes_init(len)
1292
- this.pushInstruction({ op: "local.get", index: lenTmp });
1293
- this._callStdlib("raw_bytes_init");
1294
-
1295
- const iLoc = this.acquireTemp("i32");
1296
- this.pushInstruction({ op: "i32.const", value: 0 });
1297
- this.pushInstruction({ op: "local.set", index: iLoc });
1298
-
1299
- this.pushInstruction({ op: "block", blockType: "void" });
1300
- this.pushInstruction({ op: "loop", blockType: "void" });
1301
- this.pushInstruction({ op: "local.get", index: iLoc });
1302
- this.pushInstruction({ op: "local.get", index: lenTmp });
1303
- this.pushInstruction("i32.ge_s");
1304
- this.pushInstruction({ op: "br_if", depth: 1 });
1305
-
1306
- // raw_bytes_push(arr[off + i])
1307
- this.pushInstruction({ op: "local.get", index: arrTmp });
1308
- this.pushInstruction({ op: "local.get", index: offTmp });
1309
- this.pushInstruction({ op: "local.get", index: iLoc });
1310
- this.pushInstruction("i32.add");
1311
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
1312
- this._callStdlib("raw_bytes_push");
1313
-
1314
- this.pushInstruction({ op: "local.get", index: iLoc });
1315
- this.pushInstruction({ op: "i32.const", value: 1 });
1316
- this.pushInstruction("i32.add");
1317
- this.pushInstruction({ op: "local.set", index: iLoc });
1318
- this.pushInstruction({ op: "br", depth: 0 });
1319
- this.pushInstruction("end");
1320
- this.pushInstruction("end");
1321
-
1322
- // crypto_sha256_sum()
1323
- this._callStdlib("crypto_sha256_sum");
1324
- this.pushInstruction("drop"); // 32
1325
-
1326
- // allocate [32]byte array
1327
- const arr32Info = this.mod.getArrayType(byteGo);
1328
- const outArrTmp = this.acquireTemp({
1329
- kind: "ref",
1330
- nullable: true,
1331
- typeIndex: arr32Info.typeIndex,
1332
- });
1333
- this.pushInstruction({ op: "i32.const", value: 32 });
1334
- this.pushInstruction({
1335
- op: "array.new_default",
1336
- typeIndex: arr32Info.typeIndex,
1337
- });
1338
- this.pushInstruction({ op: "local.set", index: outArrTmp });
1339
-
1340
- this.pushInstruction({ op: "i32.const", value: 0 });
1341
- this.pushInstruction({ op: "local.set", index: iLoc });
1342
-
1343
- this.pushInstruction({ op: "block", blockType: "void" });
1344
- this.pushInstruction({ op: "loop", blockType: "void" });
1345
- this.pushInstruction({ op: "local.get", index: iLoc });
1346
- this.pushInstruction({ op: "i32.const", value: 32 });
1347
- this.pushInstruction("i32.ge_s");
1348
- this.pushInstruction({ op: "br_if", depth: 1 });
1349
-
1350
- this.pushInstruction({ op: "local.get", index: outArrTmp });
1351
- this.pushInstruction({ op: "local.get", index: iLoc });
1352
- this.pushInstruction({ op: "local.get", index: iLoc });
1353
- this._callStdlib("raw_bytes_get");
1354
- this.pushInstruction({ op: "array.set", typeIndex: arr32Info.typeIndex });
1355
-
1356
- this.pushInstruction({ op: "local.get", index: iLoc });
1357
- this.pushInstruction({ op: "i32.const", value: 1 });
1358
- this.pushInstruction("i32.add");
1359
- this.pushInstruction({ op: "local.set", index: iLoc });
1360
- this.pushInstruction({ op: "br", depth: 0 });
1361
- this.pushInstruction("end");
1362
- this.pushInstruction("end");
1363
-
1364
- this.pushInstruction({ op: "local.get", index: outArrTmp });
1365
-
1366
- this.releaseTemp(outArrTmp, {
1367
- kind: "ref",
1368
- nullable: true,
1369
- typeIndex: arr32Info.typeIndex,
1370
- });
1371
- this.releaseTemp(iLoc, "i32");
1372
- this.releaseTemp(lenTmp, "i32");
1373
- this.releaseTemp(offTmp, "i32");
1374
- this.releaseTemp(arrTmp, arrW);
1375
- this.releaseTemp(sTmp, sliceW);
1376
- return;
1377
- }
1378
-
1379
- if (name === "New") {
1380
- const structInfo = this.mod.getStructType("sha256.digest");
1381
- const byteGo = { kind: "basic", name: "byte" };
1382
- const sliceInfo = this.mod.getSliceType(byteGo);
1383
- const arrInfo = sliceInfo.arrInfo;
1384
-
1385
- this.pushInstruction({ op: "ref.null", heapType: arrInfo.typeIndex });
1386
- this.pushInstruction({ op: "i32.const", value: 0 });
1387
- this.pushInstruction({ op: "i32.const", value: 0 });
1388
- this.pushInstruction({ op: "i32.const", value: 0 });
1389
- this.pushInstruction({
1390
- op: "struct.new",
1391
- typeIndex: sliceInfo.typeIndex,
1392
- });
1393
- this.pushInstruction({
1394
- op: "struct.new",
1395
- typeIndex: structInfo.typeIndex,
1396
- });
1397
- return;
1398
- }
1399
-
1400
- throw new Error(`Unsupported sha256 call: sha256.${name}`);
1401
- }
1402
-
1403
- emitHexCall(name, call, _targetWasmType) {
1404
- const args = call.args;
1405
- const byteGo = { kind: "basic", name: "byte" };
1406
- const sliceInfo = this.mod.getSliceType(byteGo);
1407
- const arrInfo = sliceInfo.arrInfo;
1408
- const sliceW = {
1409
- kind: "ref",
1410
- nullable: true,
1411
- typeIndex: sliceInfo.typeIndex,
1412
- };
1413
- const arrW = {
1414
- kind: "ref",
1415
- nullable: true,
1416
- typeIndex: arrInfo.typeIndex,
1417
- };
1418
-
1419
- if (name === "EncodedLen") {
1420
- this.emitExpr(args[0], "i64");
1421
- this.pushInstruction({ op: "i64.const", value: 2n });
1422
- this.pushInstruction("i64.mul");
1423
- return;
1424
- }
1425
-
1426
- if (name === "DecodedLen") {
1427
- this.emitExpr(args[0], "i64");
1428
- this.pushInstruction({ op: "i64.const", value: 2n });
1429
- this.pushInstruction("i64.div_s");
1430
- return;
1431
- }
1432
-
1433
- if (name === "EncodeToString") {
1434
- const sTmp = this.acquireTemp(sliceW);
1435
- this.emitExpr(args[0], sliceW);
1436
- this.pushInstruction({ op: "local.set", index: sTmp });
1437
-
1438
- const arrTmp = this.acquireTemp(arrW);
1439
- const offTmp = this.acquireTemp("i32");
1440
- const lenTmp = this.acquireTemp("i32");
1441
- this._emitSliceUnpack(sTmp, sliceInfo, {
1442
- arr: arrTmp,
1443
- off: offTmp,
1444
- len: lenTmp,
1445
- });
1446
-
1447
- this.pushInstruction({ op: "local.get", index: lenTmp });
1448
- this._callStdlib("raw_bytes_init");
1449
-
1450
- const iLoc = this.acquireTemp("i32");
1451
- this.pushInstruction({ op: "i32.const", value: 0 });
1452
- this.pushInstruction({ op: "local.set", index: iLoc });
1453
-
1454
- this.pushInstruction({ op: "block", blockType: "void" });
1455
- this.pushInstruction({ op: "loop", blockType: "void" });
1456
- this.pushInstruction({ op: "local.get", index: iLoc });
1457
- this.pushInstruction({ op: "local.get", index: lenTmp });
1458
- this.pushInstruction("i32.ge_s");
1459
- this.pushInstruction({ op: "br_if", depth: 1 });
1460
-
1461
- this.pushInstruction({ op: "local.get", index: arrTmp });
1462
- this.pushInstruction({ op: "local.get", index: offTmp });
1463
- this.pushInstruction({ op: "local.get", index: iLoc });
1464
- this.pushInstruction("i32.add");
1465
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
1466
- this._callStdlib("raw_bytes_push");
1467
-
1468
- this.pushInstruction({ op: "local.get", index: iLoc });
1469
- this.pushInstruction({ op: "i32.const", value: 1 });
1470
- this.pushInstruction("i32.add");
1471
- this.pushInstruction({ op: "local.set", index: iLoc });
1472
- this.pushInstruction({ op: "br", depth: 0 });
1473
- this.pushInstruction("end");
1474
- this.pushInstruction("end");
1475
-
1476
- this._callStdlib("hex_encode_to_string");
1477
-
1478
- this.releaseTemp(iLoc, "i32");
1479
- this.releaseTemp(lenTmp, "i32");
1480
- this.releaseTemp(offTmp, "i32");
1481
- this.releaseTemp(arrTmp, arrW);
1482
- this.releaseTemp(sTmp, sliceW);
1483
- return;
1484
- }
1485
-
1486
- if (name === "DecodeString") {
1487
- this.emitExpr(args[0], "externref");
1488
- this._callStdlib("hex_decode_string");
1489
- const nTmp = this.acquireTemp("i32");
1490
- this.pushInstruction({ op: "local.set", index: nTmp });
1491
-
1492
- this._callStdlib("hex_get_err");
1493
- const errStrTmp = this.acquireTemp("externref");
1494
- this.pushInstruction({ op: "local.set", index: errStrTmp });
1495
-
1496
- const retSliceTmp = this.acquireTemp(sliceW);
1497
- const retErrTmp = this.acquireTemp("anyref");
1498
-
1499
- this.pushInstruction({ op: "local.get", index: errStrTmp });
1500
- this.pushInstruction("ref.is_null");
1501
- this.pushInstruction("i32.eqz");
1502
- this.pushInstruction({ op: "if", blockType: "void" });
1503
-
1504
- // Error case: return nil slice, err
1505
- this.pushInstruction({ op: "ref.null", heapType: arrInfo.typeIndex });
1506
- this.pushInstruction({ op: "i32.const", value: 0 });
1507
- this.pushInstruction({ op: "i32.const", value: 0 });
1508
- this.pushInstruction({ op: "i32.const", value: 0 });
1509
- this.pushInstruction({
1510
- op: "struct.new",
1511
- typeIndex: sliceInfo.typeIndex,
1512
- });
1513
- this.pushInstruction({ op: "local.set", index: retSliceTmp });
1514
-
1515
- this.pushInstruction({ op: "local.get", index: errStrTmp });
1516
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1517
- this.pushInstruction({
1518
- op: "call",
1519
- funcIndex: this.mod.resolveFuncIndex("__mk_error"),
1520
- });
1521
- this.pushInstruction({ op: "local.set", index: retErrTmp });
1522
-
1523
- this.pushInstruction("else");
1524
-
1525
- // Success case: allocate slice and copy bytes
1526
- const outArrTmp = this.acquireTemp(arrW);
1527
- this.pushInstruction({ op: "local.get", index: nTmp });
1528
- this.pushInstruction({
1529
- op: "array.new_default",
1530
- typeIndex: arrInfo.typeIndex,
1531
- });
1532
- this.pushInstruction({ op: "local.set", index: outArrTmp });
1533
-
1534
- const iLoc = this.acquireTemp("i32");
1535
- this.pushInstruction({ op: "i32.const", value: 0 });
1536
- this.pushInstruction({ op: "local.set", index: iLoc });
1537
-
1538
- this.pushInstruction({ op: "block", blockType: "void" });
1539
- this.pushInstruction({ op: "loop", blockType: "void" });
1540
- this.pushInstruction({ op: "local.get", index: iLoc });
1541
- this.pushInstruction({ op: "local.get", index: nTmp });
1542
- this.pushInstruction("i32.ge_s");
1543
- this.pushInstruction({ op: "br_if", depth: 1 });
1544
-
1545
- this.pushInstruction({ op: "local.get", index: outArrTmp });
1546
- this.pushInstruction({ op: "local.get", index: iLoc });
1547
- this.pushInstruction({ op: "local.get", index: iLoc });
1548
- this._callStdlib("raw_bytes_get");
1549
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
1550
-
1551
- this.pushInstruction({ op: "local.get", index: iLoc });
1552
- this.pushInstruction({ op: "i32.const", value: 1 });
1553
- this.pushInstruction("i32.add");
1554
- this.pushInstruction({ op: "local.set", index: iLoc });
1555
- this.pushInstruction({ op: "br", depth: 0 });
1556
- this.pushInstruction("end");
1557
- this.pushInstruction("end");
1558
-
1559
- this.pushInstruction({ op: "local.get", index: outArrTmp });
1560
- this.pushInstruction({ op: "i32.const", value: 0 });
1561
- this.pushInstruction({ op: "local.get", index: nTmp });
1562
- this.pushInstruction({ op: "local.get", index: nTmp });
1563
- this.pushInstruction({
1564
- op: "struct.new",
1565
- typeIndex: sliceInfo.typeIndex,
1566
- });
1567
- this.pushInstruction({ op: "local.set", index: retSliceTmp });
1568
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1569
- this.pushInstruction({ op: "local.set", index: retErrTmp });
1570
-
1571
- this.releaseTemp(iLoc, "i32");
1572
- this.releaseTemp(outArrTmp, arrW);
1573
- this.pushInstruction("end");
1574
-
1575
- this.pushInstruction({ op: "local.get", index: retSliceTmp });
1576
- this.pushInstruction({ op: "local.get", index: retErrTmp });
1577
-
1578
- this.releaseTemp(retSliceTmp, sliceW);
1579
- this.releaseTemp(retErrTmp, "anyref");
1580
- this.releaseTemp(errStrTmp, "externref");
1581
- this.releaseTemp(nTmp, "i32");
1582
- return;
1583
- }
1584
-
1585
- if (name === "Encode") {
1586
- const dstTmp = this.acquireTemp(sliceW);
1587
- this.emitExpr(args[0], sliceW);
1588
- this.pushInstruction({ op: "local.set", index: dstTmp });
1589
-
1590
- const srcTmp = this.acquireTemp(sliceW);
1591
- this.emitExpr(args[1], sliceW);
1592
- this.pushInstruction({ op: "local.set", index: srcTmp });
1593
-
1594
- const srcArr = this.acquireTemp(arrW);
1595
- const srcOff = this.acquireTemp("i32");
1596
- const srcLen = this.acquireTemp("i32");
1597
- this._emitSliceUnpack(srcTmp, sliceInfo, {
1598
- arr: srcArr,
1599
- off: srcOff,
1600
- len: srcLen,
1601
- });
1602
-
1603
- this.pushInstruction({ op: "local.get", index: srcLen });
1604
- this._callStdlib("raw_bytes_init");
1605
-
1606
- const iLoc = this.acquireTemp("i32");
1607
- this.pushInstruction({ op: "i32.const", value: 0 });
1608
- this.pushInstruction({ op: "local.set", index: iLoc });
1609
-
1610
- this.pushInstruction({ op: "block", blockType: "void" });
1611
- this.pushInstruction({ op: "loop", blockType: "void" });
1612
- this.pushInstruction({ op: "local.get", index: iLoc });
1613
- this.pushInstruction({ op: "local.get", index: srcLen });
1614
- this.pushInstruction("i32.ge_s");
1615
- this.pushInstruction({ op: "br_if", depth: 1 });
1616
-
1617
- this.pushInstruction({ op: "local.get", index: srcArr });
1618
- this.pushInstruction({ op: "local.get", index: srcOff });
1619
- this.pushInstruction({ op: "local.get", index: iLoc });
1620
- this.pushInstruction("i32.add");
1621
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
1622
- this._callStdlib("raw_bytes_push");
1623
-
1624
- this.pushInstruction({ op: "local.get", index: iLoc });
1625
- this.pushInstruction({ op: "i32.const", value: 1 });
1626
- this.pushInstruction("i32.add");
1627
- this.pushInstruction({ op: "local.set", index: iLoc });
1628
- this.pushInstruction({ op: "br", depth: 0 });
1629
- this.pushInstruction("end");
1630
- this.pushInstruction("end");
1631
-
1632
- this._callStdlib("hex_encode_to_string");
1633
- const strTmp = this.acquireTemp("externref");
1634
- this.pushInstruction({ op: "local.set", index: strTmp });
1635
-
1636
- const dstArr = this.acquireTemp(arrW);
1637
- const dstOff = this.acquireTemp("i32");
1638
- const dstLen = this.acquireTemp("i32");
1639
- this._emitSliceUnpack(dstTmp, sliceInfo, {
1640
- arr: dstArr,
1641
- off: dstOff,
1642
- len: dstLen,
1643
- });
1644
-
1645
- const hexLenTmp = this.acquireTemp("i32");
1646
- this.pushInstruction({ op: "local.get", index: strTmp });
1647
- this.pushInstruction({
1648
- op: "call",
1649
- funcIndex: this.mod.getStringLenImportIndex(),
1650
- });
1651
- this.pushInstruction({ op: "local.set", index: hexLenTmp });
1652
-
1653
- this.pushInstruction({ op: "i32.const", value: 0 });
1654
- this.pushInstruction({ op: "local.set", index: iLoc });
1655
-
1656
- this.pushInstruction({ op: "block", blockType: "void" });
1657
- this.pushInstruction({ op: "loop", blockType: "void" });
1658
- this.pushInstruction({ op: "local.get", index: iLoc });
1659
- this.pushInstruction({ op: "local.get", index: hexLenTmp });
1660
- this.pushInstruction("i32.ge_s");
1661
- this.pushInstruction({ op: "br_if", depth: 1 });
1662
-
1663
- this.pushInstruction({ op: "local.get", index: dstArr });
1664
- this.pushInstruction({ op: "local.get", index: dstOff });
1665
- this.pushInstruction({ op: "local.get", index: iLoc });
1666
- this.pushInstruction("i32.add");
1667
- this.pushInstruction({ op: "local.get", index: strTmp });
1668
- this.pushInstruction({ op: "local.get", index: iLoc });
1669
- this.pushInstruction({
1670
- op: "call",
1671
- funcIndex: this.mod.getStringCodePointAtImportIndex(),
1672
- });
1673
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
1674
-
1675
- this.pushInstruction({ op: "local.get", index: iLoc });
1676
- this.pushInstruction({ op: "i32.const", value: 1 });
1677
- this.pushInstruction("i32.add");
1678
- this.pushInstruction({ op: "local.set", index: iLoc });
1679
- this.pushInstruction({ op: "br", depth: 0 });
1680
- this.pushInstruction("end");
1681
- this.pushInstruction("end");
1682
-
1683
- this.pushInstruction({ op: "local.get", index: hexLenTmp });
1684
- this.pushInstruction("i64.extend_i32_s");
1685
-
1686
- this.releaseTemp(hexLenTmp, "i32");
1687
- this.releaseTemp(dstLen, "i32");
1688
- this.releaseTemp(dstOff, "i32");
1689
- this.releaseTemp(dstArr, arrW);
1690
- this.releaseTemp(strTmp, "externref");
1691
- this.releaseTemp(iLoc, "i32");
1692
- this.releaseTemp(srcLen, "i32");
1693
- this.releaseTemp(srcOff, "i32");
1694
- this.releaseTemp(srcArr, arrW);
1695
- this.releaseTemp(srcTmp, sliceW);
1696
- this.releaseTemp(dstTmp, sliceW);
1697
- return;
1698
- }
1699
-
1700
- if (name === "Decode") {
1701
- const dstTmp = this.acquireTemp(sliceW);
1702
- this.emitExpr(args[0], sliceW);
1703
- this.pushInstruction({ op: "local.set", index: dstTmp });
1704
-
1705
- const srcTmp = this.acquireTemp(sliceW);
1706
- this.emitExpr(args[1], sliceW);
1707
- this.pushInstruction({ op: "local.set", index: srcTmp });
1708
-
1709
- const srcArr = this.acquireTemp(arrW);
1710
- const srcOff = this.acquireTemp("i32");
1711
- const srcLen = this.acquireTemp("i32");
1712
- this._emitSliceUnpack(srcTmp, sliceInfo, {
1713
- arr: srcArr,
1714
- off: srcOff,
1715
- len: srcLen,
1716
- });
1717
-
1718
- this.pushInstruction({ op: "local.get", index: srcLen });
1719
- this._callStdlib("bytes_to_str_init");
1720
-
1721
- const iLoc = this.acquireTemp("i32");
1722
- this.pushInstruction({ op: "i32.const", value: 0 });
1723
- this.pushInstruction({ op: "local.set", index: iLoc });
1724
-
1725
- this.pushInstruction({ op: "block", blockType: "void" });
1726
- this.pushInstruction({ op: "loop", blockType: "void" });
1727
- this.pushInstruction({ op: "local.get", index: iLoc });
1728
- this.pushInstruction({ op: "local.get", index: srcLen });
1729
- this.pushInstruction("i32.ge_s");
1730
- this.pushInstruction({ op: "br_if", depth: 1 });
1731
-
1732
- this.pushInstruction({ op: "local.get", index: srcArr });
1733
- this.pushInstruction({ op: "local.get", index: srcOff });
1734
- this.pushInstruction({ op: "local.get", index: iLoc });
1735
- this.pushInstruction("i32.add");
1736
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
1737
- this._callStdlib("bytes_to_str_push");
1738
-
1739
- this.pushInstruction({ op: "local.get", index: iLoc });
1740
- this.pushInstruction({ op: "i32.const", value: 1 });
1741
- this.pushInstruction("i32.add");
1742
- this.pushInstruction({ op: "local.set", index: iLoc });
1743
- this.pushInstruction({ op: "br", depth: 0 });
1744
- this.pushInstruction("end");
1745
- this.pushInstruction("end");
1746
-
1747
- this._callStdlib("bytes_to_str_finish");
1748
- this._callStdlib("hex_decode_string");
1749
- const nTmp = this.acquireTemp("i32");
1750
- this.pushInstruction({ op: "local.set", index: nTmp });
1751
-
1752
- this._callStdlib("hex_get_err");
1753
- const errStrTmp = this.acquireTemp("externref");
1754
- this.pushInstruction({ op: "local.set", index: errStrTmp });
1755
-
1756
- const retNTmp = this.acquireTemp("i64");
1757
- const retErrTmp = this.acquireTemp("anyref");
1758
-
1759
- this.pushInstruction({ op: "local.get", index: errStrTmp });
1760
- this.pushInstruction("ref.is_null");
1761
- this.pushInstruction("i32.eqz");
1762
- this.pushInstruction({ op: "if", blockType: "void" });
1763
-
1764
- // Error case
1765
- this.pushInstruction({ op: "i64.const", value: 0n });
1766
- this.pushInstruction({ op: "local.set", index: retNTmp });
1767
- this.pushInstruction({ op: "local.get", index: errStrTmp });
1768
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1769
- this.pushInstruction({
1770
- op: "call",
1771
- funcIndex: this.mod.resolveFuncIndex("__mk_error"),
1772
- });
1773
- this.pushInstruction({ op: "local.set", index: retErrTmp });
1774
-
1775
- this.pushInstruction("else");
1776
-
1777
- // Success case: copy bytes into dst
1778
- const dstArr = this.acquireTemp(arrW);
1779
- const dstOff = this.acquireTemp("i32");
1780
- const dstLen = this.acquireTemp("i32");
1781
- this._emitSliceUnpack(dstTmp, sliceInfo, {
1782
- arr: dstArr,
1783
- off: dstOff,
1784
- len: dstLen,
1785
- });
1786
-
1787
- this.pushInstruction({ op: "i32.const", value: 0 });
1788
- this.pushInstruction({ op: "local.set", index: iLoc });
1789
-
1790
- this.pushInstruction({ op: "block", blockType: "void" });
1791
- this.pushInstruction({ op: "loop", blockType: "void" });
1792
- this.pushInstruction({ op: "local.get", index: iLoc });
1793
- this.pushInstruction({ op: "local.get", index: nTmp });
1794
- this.pushInstruction("i32.ge_s");
1795
- this.pushInstruction({ op: "br_if", depth: 1 });
1796
-
1797
- this.pushInstruction({ op: "local.get", index: dstArr });
1798
- this.pushInstruction({ op: "local.get", index: dstOff });
1799
- this.pushInstruction({ op: "local.get", index: iLoc });
1800
- this.pushInstruction("i32.add");
1801
- this.pushInstruction({ op: "local.get", index: iLoc });
1802
- this._callStdlib("raw_bytes_get");
1803
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
1804
-
1805
- this.pushInstruction({ op: "local.get", index: iLoc });
1806
- this.pushInstruction({ op: "i32.const", value: 1 });
1807
- this.pushInstruction("i32.add");
1808
- this.pushInstruction({ op: "local.set", index: iLoc });
1809
- this.pushInstruction({ op: "br", depth: 0 });
1810
- this.pushInstruction("end");
1811
- this.pushInstruction("end");
1812
-
1813
- this.pushInstruction({ op: "local.get", index: nTmp });
1814
- this.pushInstruction("i64.extend_i32_s");
1815
- this.pushInstruction({ op: "local.set", index: retNTmp });
1816
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1817
- this.pushInstruction({ op: "local.set", index: retErrTmp });
1818
-
1819
- this.releaseTemp(dstLen, "i32");
1820
- this.releaseTemp(dstOff, "i32");
1821
- this.releaseTemp(dstArr, arrW);
1822
- this.pushInstruction("end");
1823
-
1824
- this.pushInstruction({ op: "local.get", index: retNTmp });
1825
- this.pushInstruction({ op: "local.get", index: retErrTmp });
1826
-
1827
- this.releaseTemp(retErrTmp, "anyref");
1828
- this.releaseTemp(retNTmp, "i64");
1829
- this.releaseTemp(errStrTmp, "externref");
1830
- this.releaseTemp(nTmp, "i32");
1831
- this.releaseTemp(iLoc, "i32");
1832
- this.releaseTemp(srcLen, "i32");
1833
- this.releaseTemp(srcOff, "i32");
1834
- this.releaseTemp(srcArr, arrW);
1835
- this.releaseTemp(srcTmp, sliceW);
1836
- this.releaseTemp(dstTmp, sliceW);
1837
- return;
1838
- }
1839
-
1840
- throw new Error(`Unsupported hex call: hex.${name}`);
1841
- }
1842
-
1843
- emitBase64Call(name, call, _targetWasmType) {
1844
- if (name === "NewEncoding") {
1845
- const structInfo = this.mod.getStructType("base64.Encoding");
1846
- this.emitExpr(call.args[0], "externref");
1847
- this._callStdlib("base64_new_encoding");
1848
- this.pushInstruction({
1849
- op: "struct.new",
1850
- typeIndex: structInfo.typeIndex,
1851
- });
1852
- return;
1853
- }
1854
- throw new Error(`Unsupported base64 call: base64.${name}`);
1855
- }
1856
-
1857
- emitBase64EncodingMethodCall(method, recvExpr, args, _targetWasmType) {
1858
- const structInfo = this.mod.getStructType("base64.Encoding");
1859
- const encW = {
1860
- kind: "ref",
1861
- nullable: true,
1862
- typeIndex: structInfo.typeIndex,
1863
- };
1864
- const modeTmp = this.acquireTemp("i32");
1865
-
1866
- if (recvExpr?.field === "URLEncoding") {
1867
- this.pushInstruction({ op: "i32.const", value: 1 });
1868
- this.pushInstruction({ op: "local.set", index: modeTmp });
1869
- } else if (recvExpr?.field === "RawStdEncoding") {
1870
- this.pushInstruction({ op: "i32.const", value: 2 });
1871
- this.pushInstruction({ op: "local.set", index: modeTmp });
1872
- } else if (recvExpr?.field === "RawURLEncoding") {
1873
- this.pushInstruction({ op: "i32.const", value: 3 });
1874
- this.pushInstruction({ op: "local.set", index: modeTmp });
1875
- } else if (recvExpr?.field === "StdEncoding") {
1876
- this.pushInstruction({ op: "i32.const", value: 0 });
1877
- this.pushInstruction({ op: "local.set", index: modeTmp });
1878
- } else {
1879
- const eTmp = this.acquireTemp(encW);
1880
- this.emitExpr(recvExpr, encW);
1881
- this.pushInstruction({ op: "local.tee", index: eTmp });
1882
- this.pushInstruction({
1883
- op: "struct.get",
1884
- typeIndex: structInfo.typeIndex,
1885
- fieldIndex: 0,
1886
- });
1887
- this.pushInstruction({ op: "local.set", index: modeTmp });
1888
- this.releaseTemp(eTmp, encW);
1889
- }
1890
-
1891
- if (method === "EncodedLen") {
1892
- const nTmp = this.acquireTemp("i64");
1893
- this.emitExpr(args[0], "i64");
1894
- this.pushInstruction({ op: "local.set", index: nTmp });
1895
-
1896
- this.pushInstruction({ op: "local.get", index: modeTmp });
1897
- this.pushInstruction({ op: "i32.const", value: 2 });
1898
- this.pushInstruction("i32.and");
1899
- this.pushInstruction({ op: "if", blockType: "i64" });
1900
- // (n * 8 + 5) / 6
1901
- this.pushInstruction({ op: "local.get", index: nTmp });
1902
- this.pushInstruction({ op: "i64.const", value: 8n });
1903
- this.pushInstruction("i64.mul");
1904
- this.pushInstruction({ op: "i64.const", value: 5n });
1905
- this.pushInstruction("i64.add");
1906
- this.pushInstruction({ op: "i64.const", value: 6n });
1907
- this.pushInstruction("i64.div_s");
1908
- this.pushInstruction("else");
1909
- // (n + 2) / 3 * 4
1910
- this.pushInstruction({ op: "local.get", index: nTmp });
1911
- this.pushInstruction({ op: "i64.const", value: 2n });
1912
- this.pushInstruction("i64.add");
1913
- this.pushInstruction({ op: "i64.const", value: 3n });
1914
- this.pushInstruction("i64.div_s");
1915
- this.pushInstruction({ op: "i64.const", value: 4n });
1916
- this.pushInstruction("i64.mul");
1917
- this.pushInstruction("end");
1918
-
1919
- this.releaseTemp(nTmp, "i64");
1920
- this.releaseTemp(modeTmp, "i32");
1921
- return;
1922
- }
1923
-
1924
- if (method === "DecodedLen") {
1925
- this.emitExpr(args[0], "i64");
1926
- this.pushInstruction({ op: "i64.const", value: 3n });
1927
- this.pushInstruction("i64.mul");
1928
- this.pushInstruction({ op: "i64.const", value: 4n });
1929
- this.pushInstruction("i64.div_s");
1930
- this.releaseTemp(modeTmp, "i32");
1931
- return;
1932
- }
1933
-
1934
- const byteGo = { kind: "basic", name: "byte" };
1935
- const sliceInfo = this.mod.getSliceType(byteGo);
1936
- const arrInfo = sliceInfo.arrInfo;
1937
- const sliceW = {
1938
- kind: "ref",
1939
- nullable: true,
1940
- typeIndex: sliceInfo.typeIndex,
1941
- };
1942
- const arrW = {
1943
- kind: "ref",
1944
- nullable: true,
1945
- typeIndex: arrInfo.typeIndex,
1946
- };
1947
-
1948
- if (method === "EncodeToString") {
1949
- const sTmp = this.acquireTemp(sliceW);
1950
- this.emitExpr(args[0], sliceW);
1951
- this.pushInstruction({ op: "local.set", index: sTmp });
1952
-
1953
- const arrTmp = this.acquireTemp(arrW);
1954
- const offTmp = this.acquireTemp("i32");
1955
- const lenTmp = this.acquireTemp("i32");
1956
- this._emitSliceUnpack(sTmp, sliceInfo, {
1957
- arr: arrTmp,
1958
- off: offTmp,
1959
- len: lenTmp,
1960
- });
1961
-
1962
- this.pushInstruction({ op: "local.get", index: lenTmp });
1963
- this._callStdlib("raw_bytes_init");
1964
-
1965
- const iLoc = this.acquireTemp("i32");
1966
- this.pushInstruction({ op: "i32.const", value: 0 });
1967
- this.pushInstruction({ op: "local.set", index: iLoc });
1968
-
1969
- this.pushInstruction({ op: "block", blockType: "void" });
1970
- this.pushInstruction({ op: "loop", blockType: "void" });
1971
- this.pushInstruction({ op: "local.get", index: iLoc });
1972
- this.pushInstruction({ op: "local.get", index: lenTmp });
1973
- this.pushInstruction("i32.ge_s");
1974
- this.pushInstruction({ op: "br_if", depth: 1 });
1975
-
1976
- this.pushInstruction({ op: "local.get", index: arrTmp });
1977
- this.pushInstruction({ op: "local.get", index: offTmp });
1978
- this.pushInstruction({ op: "local.get", index: iLoc });
1979
- this.pushInstruction("i32.add");
1980
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
1981
- this._callStdlib("raw_bytes_push");
1982
-
1983
- this.pushInstruction({ op: "local.get", index: iLoc });
1984
- this.pushInstruction({ op: "i32.const", value: 1 });
1985
- this.pushInstruction("i32.add");
1986
- this.pushInstruction({ op: "local.set", index: iLoc });
1987
- this.pushInstruction({ op: "br", depth: 0 });
1988
- this.pushInstruction("end");
1989
- this.pushInstruction("end");
1990
-
1991
- this.pushInstruction({ op: "local.get", index: modeTmp });
1992
- this._callStdlib("base64_encode_to_string");
1993
-
1994
- this.releaseTemp(iLoc, "i32");
1995
- this.releaseTemp(lenTmp, "i32");
1996
- this.releaseTemp(offTmp, "i32");
1997
- this.releaseTemp(arrTmp, arrW);
1998
- this.releaseTemp(sTmp, sliceW);
1999
- this.releaseTemp(modeTmp, "i32");
2000
- return;
2001
- }
2002
-
2003
- if (method === "DecodeString") {
2004
- this.pushInstruction({ op: "local.get", index: modeTmp });
2005
- this.emitExpr(args[0], "externref");
2006
- this._callStdlib("base64_decode_string");
2007
- const nTmp = this.acquireTemp("i32");
2008
- this.pushInstruction({ op: "local.set", index: nTmp });
2009
-
2010
- this._callStdlib("base64_get_err");
2011
- const errStrTmp = this.acquireTemp("externref");
2012
- this.pushInstruction({ op: "local.set", index: errStrTmp });
2013
-
2014
- const retSliceTmp = this.acquireTemp(sliceW);
2015
- const retErrTmp = this.acquireTemp("anyref");
2016
-
2017
- this.pushInstruction({ op: "local.get", index: errStrTmp });
2018
- this.pushInstruction("ref.is_null");
2019
- this.pushInstruction("i32.eqz");
2020
- this.pushInstruction({ op: "if", blockType: "void" });
2021
-
2022
- // Error case
2023
- this.pushInstruction({ op: "ref.null", heapType: arrInfo.typeIndex });
2024
- this.pushInstruction({ op: "i32.const", value: 0 });
2025
- this.pushInstruction({ op: "i32.const", value: 0 });
2026
- this.pushInstruction({ op: "i32.const", value: 0 });
2027
- this.pushInstruction({
2028
- op: "struct.new",
2029
- typeIndex: sliceInfo.typeIndex,
2030
- });
2031
- this.pushInstruction({ op: "local.set", index: retSliceTmp });
2032
-
2033
- this.pushInstruction({ op: "local.get", index: errStrTmp });
2034
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2035
- this.pushInstruction({
2036
- op: "call",
2037
- funcIndex: this.mod.resolveFuncIndex("__mk_error"),
2038
- });
2039
- this.pushInstruction({ op: "local.set", index: retErrTmp });
2040
-
2041
- this.pushInstruction("else");
2042
-
2043
- // Success case
2044
- const outArrTmp = this.acquireTemp(arrW);
2045
- this.pushInstruction({ op: "local.get", index: nTmp });
2046
- this.pushInstruction({
2047
- op: "array.new_default",
2048
- typeIndex: arrInfo.typeIndex,
2049
- });
2050
- this.pushInstruction({ op: "local.set", index: outArrTmp });
2051
-
2052
- const iLoc = this.acquireTemp("i32");
2053
- this.pushInstruction({ op: "i32.const", value: 0 });
2054
- this.pushInstruction({ op: "local.set", index: iLoc });
2055
-
2056
- this.pushInstruction({ op: "block", blockType: "void" });
2057
- this.pushInstruction({ op: "loop", blockType: "void" });
2058
- this.pushInstruction({ op: "local.get", index: iLoc });
2059
- this.pushInstruction({ op: "local.get", index: nTmp });
2060
- this.pushInstruction("i32.ge_s");
2061
- this.pushInstruction({ op: "br_if", depth: 1 });
2062
-
2063
- this.pushInstruction({ op: "local.get", index: outArrTmp });
2064
- this.pushInstruction({ op: "local.get", index: iLoc });
2065
- this.pushInstruction({ op: "local.get", index: iLoc });
2066
- this._callStdlib("raw_bytes_get");
2067
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
2068
-
2069
- this.pushInstruction({ op: "local.get", index: iLoc });
2070
- this.pushInstruction({ op: "i32.const", value: 1 });
2071
- this.pushInstruction("i32.add");
2072
- this.pushInstruction({ op: "local.set", index: iLoc });
2073
- this.pushInstruction({ op: "br", depth: 0 });
2074
- this.pushInstruction("end");
2075
- this.pushInstruction("end");
2076
-
2077
- this.pushInstruction({ op: "local.get", index: outArrTmp });
2078
- this.pushInstruction({ op: "i32.const", value: 0 });
2079
- this.pushInstruction({ op: "local.get", index: nTmp });
2080
- this.pushInstruction({ op: "local.get", index: nTmp });
2081
- this.pushInstruction({
2082
- op: "struct.new",
2083
- typeIndex: sliceInfo.typeIndex,
2084
- });
2085
- this.pushInstruction({ op: "local.set", index: retSliceTmp });
2086
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2087
- this.pushInstruction({ op: "local.set", index: retErrTmp });
2088
-
2089
- this.releaseTemp(iLoc, "i32");
2090
- this.releaseTemp(outArrTmp, arrW);
2091
- this.pushInstruction("end");
2092
-
2093
- this.pushInstruction({ op: "local.get", index: retSliceTmp });
2094
- this.pushInstruction({ op: "local.get", index: retErrTmp });
2095
-
2096
- this.releaseTemp(retSliceTmp, sliceW);
2097
- this.releaseTemp(retErrTmp, "anyref");
2098
- this.releaseTemp(errStrTmp, "externref");
2099
- this.releaseTemp(nTmp, "i32");
2100
- this.releaseTemp(modeTmp, "i32");
2101
- return;
2102
- }
2103
-
2104
- if (method === "Encode") {
2105
- const dstTmp = this.acquireTemp(sliceW);
2106
- this.emitExpr(args[0], sliceW);
2107
- this.pushInstruction({ op: "local.set", index: dstTmp });
2108
-
2109
- const srcTmp = this.acquireTemp(sliceW);
2110
- this.emitExpr(args[1], sliceW);
2111
- this.pushInstruction({ op: "local.set", index: srcTmp });
2112
-
2113
- const srcArr = this.acquireTemp(arrW);
2114
- const srcOff = this.acquireTemp("i32");
2115
- const srcLen = this.acquireTemp("i32");
2116
- this._emitSliceUnpack(srcTmp, sliceInfo, {
2117
- arr: srcArr,
2118
- off: srcOff,
2119
- len: srcLen,
2120
- });
2121
-
2122
- this.pushInstruction({ op: "local.get", index: srcLen });
2123
- this._callStdlib("raw_bytes_init");
2124
-
2125
- const iLoc = this.acquireTemp("i32");
2126
- this.pushInstruction({ op: "i32.const", value: 0 });
2127
- this.pushInstruction({ op: "local.set", index: iLoc });
2128
-
2129
- this.pushInstruction({ op: "block", blockType: "void" });
2130
- this.pushInstruction({ op: "loop", blockType: "void" });
2131
- this.pushInstruction({ op: "local.get", index: iLoc });
2132
- this.pushInstruction({ op: "local.get", index: srcLen });
2133
- this.pushInstruction("i32.ge_s");
2134
- this.pushInstruction({ op: "br_if", depth: 1 });
2135
-
2136
- this.pushInstruction({ op: "local.get", index: srcArr });
2137
- this.pushInstruction({ op: "local.get", index: srcOff });
2138
- this.pushInstruction({ op: "local.get", index: iLoc });
2139
- this.pushInstruction("i32.add");
2140
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
2141
- this._callStdlib("raw_bytes_push");
2142
-
2143
- this.pushInstruction({ op: "local.get", index: iLoc });
2144
- this.pushInstruction({ op: "i32.const", value: 1 });
2145
- this.pushInstruction("i32.add");
2146
- this.pushInstruction({ op: "local.set", index: iLoc });
2147
- this.pushInstruction({ op: "br", depth: 0 });
2148
- this.pushInstruction("end");
2149
- this.pushInstruction("end");
2150
-
2151
- this.pushInstruction({ op: "local.get", index: modeTmp });
2152
- this._callStdlib("base64_encode_to_string");
2153
- const strTmp = this.acquireTemp("externref");
2154
- this.pushInstruction({ op: "local.set", index: strTmp });
2155
-
2156
- const dstArr = this.acquireTemp(arrW);
2157
- const dstOff = this.acquireTemp("i32");
2158
- const dstLen = this.acquireTemp("i32");
2159
- this._emitSliceUnpack(dstTmp, sliceInfo, {
2160
- arr: dstArr,
2161
- off: dstOff,
2162
- len: dstLen,
2163
- });
2164
-
2165
- const b64LenTmp = this.acquireTemp("i32");
2166
- this.pushInstruction({ op: "local.get", index: strTmp });
2167
- this.pushInstruction({
2168
- op: "call",
2169
- funcIndex: this.mod.getStringLenImportIndex(),
2170
- });
2171
- this.pushInstruction({ op: "local.set", index: b64LenTmp });
2172
-
2173
- this.pushInstruction({ op: "i32.const", value: 0 });
2174
- this.pushInstruction({ op: "local.set", index: iLoc });
2175
-
2176
- this.pushInstruction({ op: "block", blockType: "void" });
2177
- this.pushInstruction({ op: "loop", blockType: "void" });
2178
- this.pushInstruction({ op: "local.get", index: iLoc });
2179
- this.pushInstruction({ op: "local.get", index: b64LenTmp });
2180
- this.pushInstruction("i32.ge_s");
2181
- this.pushInstruction({ op: "br_if", depth: 1 });
2182
-
2183
- this.pushInstruction({ op: "local.get", index: dstArr });
2184
- this.pushInstruction({ op: "local.get", index: dstOff });
2185
- this.pushInstruction({ op: "local.get", index: iLoc });
2186
- this.pushInstruction("i32.add");
2187
- this.pushInstruction({ op: "local.get", index: strTmp });
2188
- this.pushInstruction({ op: "local.get", index: iLoc });
2189
- this.pushInstruction({
2190
- op: "call",
2191
- funcIndex: this.mod.getStringCodePointAtImportIndex(),
2192
- });
2193
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
2194
-
2195
- this.pushInstruction({ op: "local.get", index: iLoc });
2196
- this.pushInstruction({ op: "i32.const", value: 1 });
2197
- this.pushInstruction("i32.add");
2198
- this.pushInstruction({ op: "local.set", index: iLoc });
2199
- this.pushInstruction({ op: "br", depth: 0 });
2200
- this.pushInstruction("end");
2201
- this.pushInstruction("end");
2202
-
2203
- this.releaseTemp(b64LenTmp, "i32");
2204
- this.releaseTemp(dstLen, "i32");
2205
- this.releaseTemp(dstOff, "i32");
2206
- this.releaseTemp(dstArr, arrW);
2207
- this.releaseTemp(strTmp, "externref");
2208
- this.releaseTemp(iLoc, "i32");
2209
- this.releaseTemp(srcLen, "i32");
2210
- this.releaseTemp(srcOff, "i32");
2211
- this.releaseTemp(srcArr, arrW);
2212
- this.releaseTemp(srcTmp, sliceW);
2213
- this.releaseTemp(dstTmp, sliceW);
2214
- this.releaseTemp(modeTmp, "i32");
2215
- return;
2216
- }
2217
-
2218
- if (method === "Decode") {
2219
- const dstTmp = this.acquireTemp(sliceW);
2220
- this.emitExpr(args[0], sliceW);
2221
- this.pushInstruction({ op: "local.set", index: dstTmp });
2222
-
2223
- const srcTmp = this.acquireTemp(sliceW);
2224
- this.emitExpr(args[1], sliceW);
2225
- this.pushInstruction({ op: "local.set", index: srcTmp });
2226
-
2227
- const srcArr = this.acquireTemp(arrW);
2228
- const srcOff = this.acquireTemp("i32");
2229
- const srcLen = this.acquireTemp("i32");
2230
- this._emitSliceUnpack(srcTmp, sliceInfo, {
2231
- arr: srcArr,
2232
- off: srcOff,
2233
- len: srcLen,
2234
- });
2235
-
2236
- this.pushInstruction({ op: "local.get", index: srcLen });
2237
- this._callStdlib("bytes_to_str_init");
2238
-
2239
- const iLoc = this.acquireTemp("i32");
2240
- this.pushInstruction({ op: "i32.const", value: 0 });
2241
- this.pushInstruction({ op: "local.set", index: iLoc });
2242
-
2243
- this.pushInstruction({ op: "block", blockType: "void" });
2244
- this.pushInstruction({ op: "loop", blockType: "void" });
2245
- this.pushInstruction({ op: "local.get", index: iLoc });
2246
- this.pushInstruction({ op: "local.get", index: srcLen });
2247
- this.pushInstruction("i32.ge_s");
2248
- this.pushInstruction({ op: "br_if", depth: 1 });
2249
-
2250
- this.pushInstruction({ op: "local.get", index: srcArr });
2251
- this.pushInstruction({ op: "local.get", index: srcOff });
2252
- this.pushInstruction({ op: "local.get", index: iLoc });
2253
- this.pushInstruction("i32.add");
2254
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
2255
- this._callStdlib("bytes_to_str_push");
2256
-
2257
- this.pushInstruction({ op: "local.get", index: iLoc });
2258
- this.pushInstruction({ op: "i32.const", value: 1 });
2259
- this.pushInstruction("i32.add");
2260
- this.pushInstruction({ op: "local.set", index: iLoc });
2261
- this.pushInstruction({ op: "br", depth: 0 });
2262
- this.pushInstruction("end");
2263
- this.pushInstruction("end");
2264
-
2265
- this._callStdlib("bytes_to_str_finish");
2266
- const srcStrTmp = this.acquireTemp("externref");
2267
- this.pushInstruction({ op: "local.set", index: srcStrTmp });
2268
-
2269
- this.pushInstruction({ op: "local.get", index: modeTmp });
2270
- this.pushInstruction({ op: "local.get", index: srcStrTmp });
2271
- this._callStdlib("base64_decode_string");
2272
- const nTmp = this.acquireTemp("i32");
2273
- this.pushInstruction({ op: "local.set", index: nTmp });
2274
-
2275
- this._callStdlib("base64_get_err");
2276
- const errStrTmp = this.acquireTemp("externref");
2277
- this.pushInstruction({ op: "local.set", index: errStrTmp });
2278
-
2279
- const retNTmp = this.acquireTemp("i64");
2280
- const retErrTmp = this.acquireTemp("anyref");
2281
-
2282
- this.pushInstruction({ op: "local.get", index: errStrTmp });
2283
- this.pushInstruction("ref.is_null");
2284
- this.pushInstruction("i32.eqz");
2285
- this.pushInstruction({ op: "if", blockType: "void" });
2286
-
2287
- // Error case
2288
- this.pushInstruction({ op: "i64.const", value: 0n });
2289
- this.pushInstruction({ op: "local.set", index: retNTmp });
2290
- this.pushInstruction({ op: "local.get", index: errStrTmp });
2291
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2292
- this.pushInstruction({
2293
- op: "call",
2294
- funcIndex: this.mod.resolveFuncIndex("__mk_error"),
2295
- });
2296
- this.pushInstruction({ op: "local.set", index: retErrTmp });
2297
-
2298
- this.pushInstruction("else");
2299
-
2300
- // Success case: copy bytes into dst
2301
- const dstArr = this.acquireTemp(arrW);
2302
- const dstOff = this.acquireTemp("i32");
2303
- const dstLen = this.acquireTemp("i32");
2304
- this._emitSliceUnpack(dstTmp, sliceInfo, {
2305
- arr: dstArr,
2306
- off: dstOff,
2307
- len: dstLen,
2308
- });
2309
-
2310
- this.pushInstruction({ op: "i32.const", value: 0 });
2311
- this.pushInstruction({ op: "local.set", index: iLoc });
2312
-
2313
- this.pushInstruction({ op: "block", blockType: "void" });
2314
- this.pushInstruction({ op: "loop", blockType: "void" });
2315
- this.pushInstruction({ op: "local.get", index: iLoc });
2316
- this.pushInstruction({ op: "local.get", index: nTmp });
2317
- this.pushInstruction("i32.ge_s");
2318
- this.pushInstruction({ op: "br_if", depth: 1 });
2319
-
2320
- this.pushInstruction({ op: "local.get", index: dstArr });
2321
- this.pushInstruction({ op: "local.get", index: dstOff });
2322
- this.pushInstruction({ op: "local.get", index: iLoc });
2323
- this.pushInstruction("i32.add");
2324
- this.pushInstruction({ op: "local.get", index: iLoc });
2325
- this._callStdlib("raw_bytes_get");
2326
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
2327
-
2328
- this.pushInstruction({ op: "local.get", index: iLoc });
2329
- this.pushInstruction({ op: "i32.const", value: 1 });
2330
- this.pushInstruction("i32.add");
2331
- this.pushInstruction({ op: "local.set", index: iLoc });
2332
- this.pushInstruction({ op: "br", depth: 0 });
2333
- this.pushInstruction("end");
2334
- this.pushInstruction("end");
2335
-
2336
- this.pushInstruction({ op: "local.get", index: nTmp });
2337
- this.pushInstruction("i64.extend_i32_s");
2338
- this.pushInstruction({ op: "local.set", index: retNTmp });
2339
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2340
- this.pushInstruction({ op: "local.set", index: retErrTmp });
2341
-
2342
- this.releaseTemp(dstLen, "i32");
2343
- this.releaseTemp(dstOff, "i32");
2344
- this.releaseTemp(dstArr, arrW);
2345
- this.pushInstruction("end");
2346
-
2347
- this.pushInstruction({ op: "local.get", index: retNTmp });
2348
- this.pushInstruction({ op: "local.get", index: retErrTmp });
2349
-
2350
- this.releaseTemp(retErrTmp, "anyref");
2351
- this.releaseTemp(retNTmp, "i64");
2352
- this.releaseTemp(errStrTmp, "externref");
2353
- this.releaseTemp(nTmp, "i32");
2354
- this.releaseTemp(srcStrTmp, "externref");
2355
- this.releaseTemp(iLoc, "i32");
2356
- this.releaseTemp(srcLen, "i32");
2357
- this.releaseTemp(srcOff, "i32");
2358
- this.releaseTemp(srcArr, arrW);
2359
- this.releaseTemp(srcTmp, sliceW);
2360
- this.releaseTemp(dstTmp, sliceW);
2361
- this.releaseTemp(modeTmp, "i32");
2362
- return;
2363
- }
2364
-
2365
- if (method === "WithPadding") {
2366
- const padTmp = this.acquireTemp("i64");
2367
- this.emitExpr(args[0], "i64");
2368
- this.pushInstruction({ op: "local.set", index: padTmp });
2369
-
2370
- const newModeTmp = this.acquireTemp("i32");
2371
- this.pushInstruction({ op: "local.get", index: padTmp });
2372
- this.pushInstruction({ op: "i64.const", value: -1n });
2373
- this.pushInstruction("i64.eq");
2374
- this.pushInstruction({ op: "if", blockType: "void" });
2375
- this.pushInstruction({ op: "local.get", index: modeTmp });
2376
- this.pushInstruction({ op: "i32.const", value: 1 });
2377
- this.pushInstruction("i32.and");
2378
- this.pushInstruction({ op: "i32.const", value: 2 });
2379
- this.pushInstruction("i32.or");
2380
- this.pushInstruction({ op: "local.set", index: newModeTmp });
2381
- this.pushInstruction("else");
2382
- this.pushInstruction({ op: "local.get", index: modeTmp });
2383
- this.pushInstruction({ op: "i32.const", value: 1 });
2384
- this.pushInstruction("i32.and");
2385
- this.pushInstruction({ op: "local.set", index: newModeTmp });
2386
- this.pushInstruction("end");
2387
-
2388
- this.pushInstruction({ op: "local.get", index: newModeTmp });
2389
- this.pushInstruction({
2390
- op: "struct.new",
2391
- typeIndex: structInfo.typeIndex,
2392
- });
2393
-
2394
- this.releaseTemp(newModeTmp, "i32");
2395
- this.releaseTemp(padTmp, "i64");
2396
- this.releaseTemp(modeTmp, "i32");
2397
- return;
2398
- }
2399
-
2400
- throw new Error(`Unsupported base64 method: ${method}`);
2401
- }
2402
- }