gofront 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/README.md +3 -3
  2. package/package.json +5 -4
  3. package/src/backend/js/expressions.js +849 -371
  4. package/src/backend/js/index.js +241 -147
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +512 -2547
  7. package/src/backend/js/statements.js +506 -103
  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 +177 -13
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +63 -171
  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 +643 -256
  16. package/src/backend/wasm/emit-exprs.js +124 -57
  17. package/src/backend/wasm/emit-maps.js +17 -367
  18. package/src/backend/wasm/emit-stmts.js +325 -75
  19. package/src/backend/wasm/emit.js +104 -13
  20. package/src/backend/wasm/globals.js +47 -8
  21. package/src/backend/wasm/glue.js +2 -4
  22. package/src/backend/wasm/index.js +36 -530
  23. package/src/backend/wasm/method-expr.js +12 -1
  24. package/src/backend/wasm/module-emitter.js +92 -717
  25. package/src/backend/wasm/monomorph.js +103 -6
  26. package/src/backend/wasm/natives.js +596 -0
  27. package/src/backend/wasm/prescan.js +5 -153
  28. package/src/backend/wasm/prune-funcs.js +89 -0
  29. package/src/backend/wasm/stdlib/index.js +2 -32
  30. package/src/backend/wasm/types.js +68 -20
  31. package/src/backend/wasm/variadic.js +3 -3
  32. package/src/cli/cli-core.js +5 -1
  33. package/src/cli/test-runner.js +115 -342
  34. package/src/compiler.js +108 -130
  35. package/src/lexer/lexer.js +105 -11
  36. package/src/lexer/templ-lexer.js +61 -18
  37. package/src/lexer/tokens.js +1 -0
  38. package/src/link/stdlib.js +354 -132
  39. package/src/link/type-names.js +148 -0
  40. package/src/link/wasm.js +30 -6
  41. package/src/lower/bounds.js +153 -0
  42. package/src/lower/captures.js +92 -33
  43. package/src/lower/embedding.js +32 -3
  44. package/src/lower/errors-as.js +196 -0
  45. package/src/lower/fmt-formatters.js +905 -0
  46. package/src/lower/functions.js +2 -0
  47. package/src/lower/gen-types.js +274 -0
  48. package/src/lower/index.js +7 -1
  49. package/src/lower/json-codecs.js +228 -247
  50. package/src/lower/ownership.js +25 -7
  51. package/src/lower/reachability.js +69 -51
  52. package/src/lower/walk.js +12 -0
  53. package/src/parser/declarations.js +28 -5
  54. package/src/parser/expressions.js +86 -16
  55. package/src/parser/statements.js +1 -0
  56. package/src/parser/templ.js +44 -5
  57. package/src/parser/types.js +1 -0
  58. package/src/resolver.js +1 -2
  59. package/src/typechecker/assignability.js +124 -11
  60. package/src/typechecker/const-fold.js +70 -27
  61. package/src/typechecker/constants.js +32 -6
  62. package/src/typechecker/expressions.js +326 -98
  63. package/src/typechecker/index.js +208 -33
  64. package/src/typechecker/init-order.js +136 -40
  65. package/src/typechecker/operand-text.js +40 -0
  66. package/src/typechecker/resolve.js +192 -36
  67. package/src/typechecker/statements.js +122 -11
  68. package/src/typechecker/stdlib/excluded.js +9 -5
  69. package/src/typechecker/stdlib/index.js +25 -9
  70. package/src/typechecker/termination.js +10 -1
  71. package/src/typechecker/types.js +203 -573
  72. package/stdlib/bytes/buffer.go +479 -0
  73. package/stdlib/bytes/bytes.go +1010 -0
  74. package/stdlib/bytes/reader.go +161 -0
  75. package/stdlib/context/context.go +115 -0
  76. package/stdlib/crypto/rand/rand.go +34 -0
  77. package/stdlib/crypto/sha256/sha256.go +249 -0
  78. package/stdlib/encoding/base64/base64.go +331 -0
  79. package/stdlib/encoding/binary/binary.go +332 -0
  80. package/stdlib/encoding/hex/hex.go +140 -0
  81. package/stdlib/encoding/json/json.go +62 -0
  82. package/stdlib/errors/errors.go +174 -0
  83. package/stdlib/fmt/errors.go +110 -0
  84. package/stdlib/fmt/format.go +732 -0
  85. package/stdlib/fmt/print.go +1232 -0
  86. package/stdlib/gom/gom.go +293 -0
  87. package/stdlib/html/html.go +251 -0
  88. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  89. package/stdlib/internal/jsonrt/dec.go +171 -38
  90. package/stdlib/internal/jsonrt/enc.go +186 -36
  91. package/stdlib/internal/jsonrt/scanner.go +17 -8
  92. package/stdlib/io/io.go +157 -1
  93. package/stdlib/maps/maps.go +131 -0
  94. package/stdlib/math/bits/bits.go +507 -0
  95. package/stdlib/math/extra.go +16 -14
  96. package/stdlib/math/math.go +439 -0
  97. package/stdlib/math/rand/rand.go +297 -0
  98. package/stdlib/os/os.go +93 -0
  99. package/stdlib/path/filepath/filepath.go +47 -0
  100. package/stdlib/path/path.go +394 -0
  101. package/stdlib/regexp/regexp.go +231 -0
  102. package/stdlib/slices/slices.go +526 -0
  103. package/stdlib/slices/sort.go +209 -0
  104. package/stdlib/slices/zsort_cmp.go +480 -0
  105. package/stdlib/slices/zsort_ordered.go +482 -0
  106. package/stdlib/sort/sort.go +391 -452
  107. package/stdlib/sort/zsort_func.go +480 -0
  108. package/stdlib/sort/zsort_iface.go +480 -0
  109. package/stdlib/strconv/float.go +1699 -0
  110. package/stdlib/strconv/isprint.go +752 -0
  111. package/stdlib/strconv/quote.go +235 -50
  112. package/stdlib/strconv/strconv.go +616 -0
  113. package/stdlib/strings/builder.go +95 -0
  114. package/stdlib/strings/reader.go +163 -0
  115. package/stdlib/strings/replacer.go +102 -0
  116. package/stdlib/strings/strings.go +807 -0
  117. package/stdlib/sync/sync.go +268 -0
  118. package/stdlib/testing/async_js.go +61 -0
  119. package/stdlib/testing/benchmark.go +297 -0
  120. package/stdlib/testing/testing.go +523 -0
  121. package/stdlib/time/duration.go +233 -0
  122. package/stdlib/time/format.go +745 -0
  123. package/stdlib/time/parse.go +790 -0
  124. package/stdlib/time/sleep_js.go +63 -0
  125. package/stdlib/time/time.go +834 -0
  126. package/stdlib/unicode/unicode.go +141 -3
  127. package/stdlib/unicode/utf8/utf8.go +464 -0
  128. package/src/backend/js/fmt-runtime.js +0 -573
  129. package/src/backend/js/stdlib/base64.js +0 -12
  130. package/src/backend/js/stdlib/binary.js +0 -102
  131. package/src/backend/js/stdlib/bits.js +0 -119
  132. package/src/backend/js/stdlib/builder.js +0 -98
  133. package/src/backend/js/stdlib/bytes.js +0 -368
  134. package/src/backend/js/stdlib/errors.js +0 -45
  135. package/src/backend/js/stdlib/fmt.js +0 -517
  136. package/src/backend/js/stdlib/gom.js +0 -155
  137. package/src/backend/js/stdlib/hex.js +0 -17
  138. package/src/backend/js/stdlib/html.js +0 -20
  139. package/src/backend/js/stdlib/io.js +0 -137
  140. package/src/backend/js/stdlib/json.js +0 -1167
  141. package/src/backend/js/stdlib/maps.js +0 -37
  142. package/src/backend/js/stdlib/math.js +0 -85
  143. package/src/backend/js/stdlib/os.js +0 -13
  144. package/src/backend/js/stdlib/path.js +0 -48
  145. package/src/backend/js/stdlib/rand.js +0 -32
  146. package/src/backend/js/stdlib/regexp.js +0 -54
  147. package/src/backend/js/stdlib/sha256.js +0 -12
  148. package/src/backend/js/stdlib/shared.js +0 -17
  149. package/src/backend/js/stdlib/simd.js +0 -34
  150. package/src/backend/js/stdlib/slices.js +0 -107
  151. package/src/backend/js/stdlib/sort.js +0 -30
  152. package/src/backend/js/stdlib/strconv.js +0 -79
  153. package/src/backend/js/stdlib/strings.js +0 -301
  154. package/src/backend/js/stdlib/sync.js +0 -13
  155. package/src/backend/js/stdlib/testing.js +0 -41
  156. package/src/backend/js/stdlib/time.js +0 -152
  157. package/src/backend/js/stdlib/unicode.js +0 -25
  158. package/src/backend/js/stdlib/utf8.js +0 -26
  159. package/src/backend/wasm/stdlib/bytes.js +0 -6716
  160. package/src/backend/wasm/stdlib/core.js +0 -10278
  161. package/src/backend/wasm/stdlib/io.js +0 -3578
  162. package/src/backend/wasm/stdlib/packages.js +0 -2402
  163. package/src/backend/wasm/stdlib/pure.js +0 -720
  164. package/src/backend/wasm/stdlib/time.js +0 -2229
  165. package/src/typechecker/stdlib/core.js +0 -1079
  166. package/src/typechecker/stdlib/extended.js +0 -1210
  167. package/stdlib/bytes/iter.go +0 -192
  168. package/stdlib/bytes/search.go +0 -240
  169. package/stdlib/bytes/split.go +0 -218
  170. package/stdlib/errors/overlay.go +0 -12
  171. package/stdlib/maps/iter.go +0 -65
  172. package/stdlib/slices/extra.go +0 -73
  173. package/stdlib/slices/iter.go +0 -113
  174. package/stdlib/strings/extra.go +0 -35
  175. package/stdlib/strings/iter.go +0 -122
  176. package/stdlib/sync/extra.go +0 -105
  177. package/stdlib/unicode/utf8/bytes.go +0 -239
@@ -1,3578 +0,0 @@
1
- // src/backend/wasm/stdlib/io.js
2
- // FunctionEmitter mixin: io, readers/writers, fmt.Fprint*, fmt.Sscan*.
3
-
4
- import { toWasmType } from "../types.js";
5
-
6
- export class IoEmitter {
7
- _isIoConst(expr) {
8
- return (
9
- this._isPkgExpr(expr, "io") &&
10
- (expr.field === "EOF" || expr.field === "Discard")
11
- );
12
- }
13
-
14
- _isOsConst(expr) {
15
- return (
16
- this._isPkgExpr(expr, "os") &&
17
- (expr.field === "Stdout" ||
18
- expr.field === "Stderr" ||
19
- expr.field === "Stdin")
20
- );
21
- }
22
-
23
- emitOsConst(field, targetWasmType) {
24
- const gIdx = this.mod.getOsGlobalIndex(field);
25
- const fileInfo = this.mod.getStructType("os.File");
26
- const fd = field === "Stdout" ? 1 : field === "Stderr" ? 2 : 0;
27
- this.pushInstruction({ op: "global.get", index: gIdx });
28
- this.pushInstruction("ref.is_null");
29
- this.pushInstruction({ op: "if", blockType: "void" });
30
- if (fileInfo) {
31
- this.pushInstruction({ op: "i64.const", value: BigInt(fd) });
32
- this.pushInstruction({
33
- op: "struct.new",
34
- typeIndex: fileInfo.typeIndex,
35
- });
36
- } else {
37
- this.pushInstruction({ op: "ref.null", heapType: "any" });
38
- }
39
- this.pushInstruction({ op: "global.set", index: gIdx });
40
- this.pushInstruction("end");
41
- this.pushInstruction({ op: "global.get", index: gIdx });
42
- if (fileInfo && targetWasmType && targetWasmType !== "anyref") {
43
- this.pushInstruction({
44
- op: "ref.cast",
45
- typeIndex: fileInfo.typeIndex,
46
- });
47
- }
48
- }
49
-
50
- emitIoConst(field, _targetWasmType) {
51
- if (field === "EOF") {
52
- this._emitLazyErrorGlobal(this.mod.getIoErrGlobalIndex("EOF"), "EOF");
53
- return;
54
- }
55
- if (field === "Discard") {
56
- const gIdx = this.mod.getIoDiscardGlobalIndex();
57
- const discardInfo = this.mod.getStructType("io.discard");
58
- this.pushInstruction({ op: "global.get", index: gIdx });
59
- this.pushInstruction("ref.is_null");
60
- this.pushInstruction({ op: "if", blockType: "void" });
61
- if (discardInfo) {
62
- this.pushInstruction({
63
- op: "struct.new",
64
- typeIndex: discardInfo.typeIndex,
65
- });
66
- } else {
67
- this.pushInstruction({ op: "ref.null", heapType: "any" });
68
- }
69
- this.pushInstruction({ op: "global.set", index: gIdx });
70
- this.pushInstruction("end");
71
- this.pushInstruction({ op: "global.get", index: gIdx });
72
- return;
73
- }
74
- throw new Error(`Unsupported io constant: ${field}`);
75
- }
76
-
77
- emitIoCall(name, call, targetWasmType) {
78
- if (name === "WriteString") {
79
- this._emitIoWriteString(call, targetWasmType);
80
- return;
81
- }
82
- if (name === "ReadAll") {
83
- this._emitIoReadAll(call, targetWasmType);
84
- return;
85
- }
86
- if (name === "LimitReader") {
87
- this._emitIoLimitReader(call, targetWasmType);
88
- return;
89
- }
90
- if (name === "Copy") {
91
- this._emitIoCopy(call, targetWasmType);
92
- return;
93
- }
94
- if (name === "CopyN") {
95
- this._emitIoCopyN(call, targetWasmType);
96
- return;
97
- }
98
- throw new Error(`Unsupported io call: ${name}`);
99
- }
100
-
101
- _emitIoWriteString(call, _targetWasmType) {
102
- const wExpr = call.args[0];
103
- const strExpr = call.args[1];
104
- const strTmp = this.acquireTemp("externref");
105
- this.emitExpr(strExpr, "externref");
106
- this.pushInstruction({ op: "local.set", index: strTmp });
107
- this._emitWriterWrite(wExpr, strTmp);
108
- this.releaseTemp(strTmp, "externref");
109
- }
110
-
111
- _emitWriterWrite(wExpr, strTmp) {
112
- const wType = wExpr._type ?? this._resolveExprGoType(wExpr);
113
- const targetName =
114
- wType?.name ?? (wType?.kind === "pointer" ? wType.base?.name : null);
115
- if (targetName === "strings.Builder") {
116
- const builderInfo = this.mod.getStructType("strings.Builder");
117
- const builderW = {
118
- kind: "ref",
119
- nullable: true,
120
- typeIndex: builderInfo.typeIndex,
121
- };
122
- const bTmp = this.acquireTemp(builderW);
123
- this.emitExpr(wExpr, builderW);
124
- this.pushInstruction({ op: "local.set", index: bTmp });
125
- this._emitBuilderWriteStringCore(bTmp, strTmp);
126
- this.releaseTemp(bTmp, builderW);
127
- this.pushInstruction({ op: "local.get", index: strTmp });
128
- this.pushInstruction({
129
- op: "call",
130
- funcIndex: this.mod.getStringLenImportIndex(),
131
- });
132
- this.pushInstruction("i64.extend_i32_u");
133
- this.pushInstruction({ op: "ref.null", heapType: "any" });
134
- return;
135
- }
136
- if (targetName === "bytes.Buffer") {
137
- const bufInfo = this.mod.getStructType("bytes.Buffer");
138
- const bufW = {
139
- kind: "ref",
140
- nullable: true,
141
- typeIndex: bufInfo.typeIndex,
142
- };
143
- const bTmp = this.acquireTemp(bufW);
144
- this.emitExpr(wExpr, bufW);
145
- this.pushInstruction({ op: "local.set", index: bTmp });
146
- this._emitBufferWriteStringCore(bTmp, strTmp);
147
- this.releaseTemp(bTmp, bufW);
148
- this.pushInstruction({ op: "local.get", index: strTmp });
149
- this.pushInstruction({
150
- op: "call",
151
- funcIndex: this.mod.getStringLenImportIndex(),
152
- });
153
- this.pushInstruction("i64.extend_i32_u");
154
- this.pushInstruction({ op: "ref.null", heapType: "any" });
155
- return;
156
- }
157
- if (targetName === "os.File") {
158
- this.pushInstruction({ op: "local.get", index: strTmp });
159
- this._callStdlib("fmt_print_raw");
160
- this.pushInstruction({ op: "local.get", index: strTmp });
161
- this.pushInstruction({
162
- op: "call",
163
- funcIndex: this.mod.getStringLenImportIndex(),
164
- });
165
- this.pushInstruction("i64.extend_i32_u");
166
- this.pushInstruction({ op: "ref.null", heapType: "any" });
167
- return;
168
- }
169
-
170
- const wTmp = this.acquireTemp("anyref");
171
- this.emitExpr(wExpr, "anyref");
172
- this.pushInstruction({ op: "local.set", index: wTmp });
173
-
174
- this.pushInstruction({ op: "local.get", index: wTmp });
175
- this.pushInstruction({ op: "local.get", index: strTmp });
176
- this._emitStringToByteSlice({ elem: { kind: "basic", name: "byte" } });
177
-
178
- const dispatchIdx = this.mod.resolveFuncIndex("__dispatch_io.Writer_Write");
179
- if (dispatchIdx !== null) {
180
- this.pushInstruction({ op: "call", funcIndex: dispatchIdx });
181
- } else {
182
- this.pushInstruction({ op: "i64.const", value: 0n });
183
- this.pushInstruction({ op: "ref.null", heapType: "any" });
184
- }
185
- this.releaseTemp(wTmp, "anyref");
186
- }
187
-
188
- _emitIoReadAll(call, _targetWasmType) {
189
- const rExpr = call.args[0];
190
- const rTmp = this.acquireTemp("anyref");
191
- this.emitExpr(rExpr, "anyref");
192
- this.pushInstruction({ op: "local.set", index: rTmp });
193
-
194
- const byteElemGo = { kind: "basic", name: "byte" };
195
- const sliceInfo = this.mod.getSliceType(byteElemGo);
196
- const arrInfo = sliceInfo.arrInfo;
197
- const sliceW = {
198
- kind: "ref",
199
- nullable: true,
200
- typeIndex: sliceInfo.typeIndex,
201
- };
202
- const arrW = { kind: "ref", nullable: true, typeIndex: arrInfo.typeIndex };
203
-
204
- // chunks slice (len: 0, cap: 512)
205
- const chunksTmp = this.acquireTemp(sliceW);
206
- this.pushInstruction({ op: "i32.const", value: 512 });
207
- this.pushInstruction({
208
- op: "array.new_default",
209
- typeIndex: arrInfo.typeIndex,
210
- });
211
- this.pushInstruction({ op: "i32.const", value: 0 });
212
- this.pushInstruction({ op: "i32.const", value: 0 });
213
- this.pushInstruction({ op: "i32.const", value: 512 });
214
- this.pushInstruction({
215
- op: "struct.new",
216
- typeIndex: sliceInfo.typeIndex,
217
- });
218
- this.pushInstruction({ op: "local.set", index: chunksTmp });
219
-
220
- // buf slice (len: 512, cap: 512)
221
- const bufTmp = this.acquireTemp(sliceW);
222
- this.pushInstruction({ op: "i32.const", value: 512 });
223
- this.pushInstruction({
224
- op: "array.new_default",
225
- typeIndex: arrInfo.typeIndex,
226
- });
227
- this.pushInstruction({ op: "i32.const", value: 0 });
228
- this.pushInstruction({ op: "i32.const", value: 512 });
229
- this.pushInstruction({ op: "i32.const", value: 512 });
230
- this.pushInstruction({
231
- op: "struct.new",
232
- typeIndex: sliceInfo.typeIndex,
233
- });
234
- this.pushInstruction({ op: "local.set", index: bufTmp });
235
-
236
- const errTmp = this.acquireTemp("anyref");
237
- this.pushInstruction({ op: "ref.null", heapType: "any" });
238
- this.pushInstruction({ op: "local.set", index: errTmp });
239
-
240
- const dispatchIdx = this.mod.resolveFuncIndex("__dispatch_io.Reader_Read");
241
-
242
- this.pushInstruction({ op: "block", blockType: "void" });
243
- this.pushInstruction({ op: "loop", blockType: "void" });
244
-
245
- this.pushInstruction({ op: "local.get", index: rTmp });
246
- this.pushInstruction({ op: "local.get", index: bufTmp });
247
- if (dispatchIdx !== null) {
248
- this.pushInstruction({ op: "call", funcIndex: dispatchIdx });
249
- } else {
250
- this.pushInstruction({ op: "i64.const", value: 0n });
251
- this.pushInstruction({ op: "ref.null", heapType: "any" });
252
- }
253
-
254
- // (n: i64, e: anyref)
255
- this.pushInstruction({ op: "local.set", index: errTmp });
256
- const nTmp = this.acquireTemp("i32");
257
- this.pushInstruction("i32.wrap_i64");
258
- this.pushInstruction({ op: "local.set", index: nTmp });
259
-
260
- // if n > 0, append buf[0:n] to chunks
261
- this.pushInstruction({ op: "local.get", index: nTmp });
262
- this.pushInstruction({ op: "i32.const", value: 0 });
263
- this.pushInstruction("i32.gt_s");
264
- this.pushInstruction({ op: "if", blockType: "void" });
265
- this._emitAppendSliceBytes(chunksTmp, bufTmp, nTmp, sliceInfo, arrW);
266
- this.pushInstruction("end");
267
- this.releaseTemp(nTmp, "i32");
268
-
269
- // if err != nil: if errors.Is(err, io.EOF) err = nil; break loop
270
- this.pushInstruction({ op: "local.get", index: errTmp });
271
- this.pushInstruction("ref.is_null");
272
- this.pushInstruction("i32.eqz");
273
- this.pushInstruction({ op: "if", blockType: "void" });
274
- this.pushInstruction({ op: "local.get", index: errTmp });
275
- this.emitIoConst("EOF", "anyref");
276
- this.pushInstruction({
277
- op: "call",
278
- funcIndex: this.mod.resolveFuncIndex("__errors_is"),
279
- });
280
- this.pushInstruction({ op: "if", blockType: "void" });
281
- this.pushInstruction({ op: "ref.null", heapType: "any" });
282
- this.pushInstruction({ op: "local.set", index: errTmp });
283
- this.pushInstruction("end");
284
- this.pushInstruction({ op: "br", depth: 2 });
285
- this.pushInstruction("end");
286
-
287
- this.pushInstruction({ op: "br", depth: 0 });
288
- this.pushInstruction("end");
289
- this.pushInstruction("end");
290
-
291
- this.pushInstruction({ op: "local.get", index: chunksTmp });
292
- this.pushInstruction({ op: "local.get", index: errTmp });
293
-
294
- this.releaseTemp(errTmp, "anyref");
295
- this.releaseTemp(bufTmp, sliceW);
296
- this.releaseTemp(chunksTmp, sliceW);
297
- this.releaseTemp(rTmp, "anyref");
298
- }
299
-
300
- _emitIoLimitReader(call, _targetWasmType) {
301
- const lrInfo = this.mod.getStructType("io.LimitedReader");
302
- if (!lrInfo) {
303
- throw new Error("io.LimitedReader struct type not found");
304
- }
305
- this.emitExpr(call.args[0], "anyref");
306
- this.emitExpr(call.args[1], "i64");
307
- this.pushInstruction({
308
- op: "struct.new",
309
- typeIndex: lrInfo.typeIndex,
310
- });
311
- }
312
-
313
- _emitIoCopy(call, _targetWasmType) {
314
- const dstTmp = this.acquireTemp("anyref");
315
- const srcTmp = this.acquireTemp("anyref");
316
- this.emitExpr(call.args[0], "anyref");
317
- this.pushInstruction({ op: "local.set", index: dstTmp });
318
- this.emitExpr(call.args[1], "anyref");
319
- this.pushInstruction({ op: "local.set", index: srcTmp });
320
-
321
- this._emitIoCopyCore(dstTmp, srcTmp);
322
-
323
- this.releaseTemp(srcTmp, "anyref");
324
- this.releaseTemp(dstTmp, "anyref");
325
- }
326
-
327
- _emitIoCopyN(call, _targetWasmType) {
328
- const lrInfo = this.mod.getStructType("io.LimitedReader");
329
- if (!lrInfo) {
330
- throw new Error("io.LimitedReader struct type not found");
331
- }
332
- const dstTmp = this.acquireTemp("anyref");
333
- const srcTmp = this.acquireTemp("anyref");
334
- const nTmp = this.acquireTemp("i64");
335
- this.emitExpr(call.args[0], "anyref");
336
- this.pushInstruction({ op: "local.set", index: dstTmp });
337
- this.emitExpr(call.args[1], "anyref");
338
- this.pushInstruction({ op: "local.set", index: srcTmp });
339
- this.emitExpr(call.args[2], "i64");
340
- this.pushInstruction({ op: "local.set", index: nTmp });
341
-
342
- const lrW = {
343
- kind: "ref",
344
- nullable: true,
345
- typeIndex: lrInfo.typeIndex,
346
- };
347
- const lrTmp = this.acquireTemp(lrW);
348
- this.pushInstruction({ op: "local.get", index: srcTmp });
349
- this.pushInstruction({ op: "local.get", index: nTmp });
350
- this.pushInstruction({
351
- op: "struct.new",
352
- typeIndex: lrInfo.typeIndex,
353
- });
354
- this.pushInstruction({ op: "local.set", index: lrTmp });
355
-
356
- this._emitIoCopyCore(dstTmp, lrTmp);
357
-
358
- const resErrTmp = this.acquireTemp("anyref");
359
- const writtenTmp = this.acquireTemp("i64");
360
- this.pushInstruction({ op: "local.set", index: resErrTmp });
361
- this.pushInstruction({ op: "local.set", index: writtenTmp });
362
-
363
- // if written == n: err = nil
364
- this.pushInstruction({ op: "local.get", index: writtenTmp });
365
- this.pushInstruction({ op: "local.get", index: nTmp });
366
- this.pushInstruction("i64.eq");
367
- this.pushInstruction({ op: "if", blockType: "void" });
368
- this.pushInstruction({ op: "ref.null", heapType: "any" });
369
- this.pushInstruction({ op: "local.set", index: resErrTmp });
370
- this.pushInstruction("else");
371
- // if written < n && resErr == nil: resErr = io.EOF
372
- this.pushInstruction({ op: "local.get", index: writtenTmp });
373
- this.pushInstruction({ op: "local.get", index: nTmp });
374
- this.pushInstruction("i64.lt_s");
375
- this.pushInstruction({ op: "local.get", index: resErrTmp });
376
- this.pushInstruction("ref.is_null");
377
- this.pushInstruction("i32.and");
378
- this.pushInstruction({ op: "if", blockType: "void" });
379
- this.emitIoConst("EOF", "anyref");
380
- this.pushInstruction({ op: "local.set", index: resErrTmp });
381
- this.pushInstruction("end");
382
- this.pushInstruction("end");
383
-
384
- this.pushInstruction({ op: "local.get", index: writtenTmp });
385
- this.pushInstruction({ op: "local.get", index: resErrTmp });
386
-
387
- this.releaseTemp(writtenTmp, "i64");
388
- this.releaseTemp(resErrTmp, "anyref");
389
- this.releaseTemp(lrTmp, lrW);
390
- this.releaseTemp(nTmp, "i64");
391
- this.releaseTemp(srcTmp, "anyref");
392
- this.releaseTemp(dstTmp, "anyref");
393
- }
394
-
395
- _emitIoCopyCore(dstTmp, srcTmp) {
396
- const byteElemGo = { kind: "basic", name: "byte" };
397
- const sliceInfo = this.mod.getSliceType(byteElemGo);
398
- const arrInfo = sliceInfo.arrInfo;
399
- const sliceW = {
400
- kind: "ref",
401
- nullable: true,
402
- typeIndex: sliceInfo.typeIndex,
403
- };
404
- const arrW = { kind: "ref", nullable: true, typeIndex: arrInfo.typeIndex };
405
-
406
- // Buffer: 32KB
407
- const bufSize = 32768;
408
- const bufArrTmp = this.acquireTemp(arrW);
409
- this.pushInstruction({ op: "i32.const", value: bufSize });
410
- this.pushInstruction({
411
- op: "array.new_default",
412
- typeIndex: arrInfo.typeIndex,
413
- });
414
- this.pushInstruction({ op: "local.set", index: bufArrTmp });
415
-
416
- const bufTmp = this.acquireTemp(sliceW);
417
- this.pushInstruction({ op: "local.get", index: bufArrTmp });
418
- this.pushInstruction({ op: "i32.const", value: 0 });
419
- this.pushInstruction({ op: "i32.const", value: bufSize });
420
- this.pushInstruction({ op: "i32.const", value: bufSize });
421
- this.pushInstruction({
422
- op: "struct.new",
423
- typeIndex: sliceInfo.typeIndex,
424
- });
425
- this.pushInstruction({ op: "local.set", index: bufTmp });
426
-
427
- const totalWrittenTmp = this.acquireTemp("i64");
428
- this.pushInstruction({ op: "i64.const", value: 0n });
429
- this.pushInstruction({ op: "local.set", index: totalWrittenTmp });
430
-
431
- const errTmp = this.acquireTemp("anyref");
432
- this.pushInstruction({ op: "ref.null", heapType: "any" });
433
- this.pushInstruction({ op: "local.set", index: errTmp });
434
-
435
- const readErrTmp = this.acquireTemp("anyref");
436
- const nrI32Tmp = this.acquireTemp("i32");
437
- const subsliceTmp = this.acquireTemp(sliceW);
438
- const writeErrTmp = this.acquireTemp("anyref");
439
- const nwTmp = this.acquireTemp("i64");
440
-
441
- const dispatchReadIdx = this.mod.resolveFuncIndex(
442
- "__dispatch_io.Reader_Read",
443
- );
444
- const dispatchWriteIdx = this.mod.resolveFuncIndex(
445
- "__dispatch_io.Writer_Write",
446
- );
447
-
448
- this.pushInstruction({ op: "block", blockType: "void" });
449
- this.pushInstruction({ op: "loop", blockType: "void" });
450
-
451
- // Read: src.Read(buf)
452
- this.pushInstruction({ op: "local.get", index: srcTmp });
453
- this.pushInstruction({ op: "local.get", index: bufTmp });
454
- if (dispatchReadIdx !== null) {
455
- this.pushInstruction({ op: "call", funcIndex: dispatchReadIdx });
456
- } else {
457
- this.pushInstruction({ op: "i64.const", value: 0n });
458
- this.pushInstruction({ op: "ref.null", heapType: "any" });
459
- }
460
- this.pushInstruction({ op: "local.set", index: readErrTmp });
461
- this.pushInstruction("i32.wrap_i64");
462
- this.pushInstruction({ op: "local.set", index: nrI32Tmp });
463
-
464
- // if nr > 0: write
465
- this.pushInstruction({ op: "local.get", index: nrI32Tmp });
466
- this.pushInstruction({ op: "i32.const", value: 0 });
467
- this.pushInstruction("i32.gt_s");
468
- this.pushInstruction({ op: "if", blockType: "void" });
469
-
470
- // subslice = slice(bufArrTmp, 0, nrI32Tmp, nrI32Tmp)
471
- this.pushInstruction({ op: "local.get", index: bufArrTmp });
472
- this.pushInstruction({ op: "i32.const", value: 0 });
473
- this.pushInstruction({ op: "local.get", index: nrI32Tmp });
474
- this.pushInstruction({ op: "local.get", index: nrI32Tmp });
475
- this.pushInstruction({
476
- op: "struct.new",
477
- typeIndex: sliceInfo.typeIndex,
478
- });
479
- this.pushInstruction({ op: "local.set", index: subsliceTmp });
480
-
481
- // dst.Write(subslice)
482
- this.pushInstruction({ op: "local.get", index: dstTmp });
483
- this.pushInstruction({ op: "local.get", index: subsliceTmp });
484
- if (dispatchWriteIdx !== null) {
485
- this.pushInstruction({ op: "call", funcIndex: dispatchWriteIdx });
486
- } else {
487
- this.pushInstruction({ op: "i64.const", value: 0n });
488
- this.pushInstruction({ op: "ref.null", heapType: "any" });
489
- }
490
- this.pushInstruction({ op: "local.set", index: writeErrTmp });
491
- this.pushInstruction({ op: "local.set", index: nwTmp });
492
-
493
- // totalWritten += nw
494
- this.pushInstruction({ op: "local.get", index: nwTmp });
495
- this.pushInstruction({ op: "i64.const", value: 0n });
496
- this.pushInstruction("i64.gt_s");
497
- this.pushInstruction({ op: "if", blockType: "void" });
498
- this.pushInstruction({ op: "local.get", index: totalWrittenTmp });
499
- this.pushInstruction({ op: "local.get", index: nwTmp });
500
- this.pushInstruction("i64.add");
501
- this.pushInstruction({ op: "local.set", index: totalWrittenTmp });
502
- this.pushInstruction("end");
503
-
504
- // if writeErr != nil: err = writeErr; br 2 (break loop)
505
- this.pushInstruction({ op: "local.get", index: writeErrTmp });
506
- this.pushInstruction("ref.is_null");
507
- this.pushInstruction("i32.eqz");
508
- this.pushInstruction({ op: "if", blockType: "void" });
509
- this.pushInstruction({ op: "local.get", index: writeErrTmp });
510
- this.pushInstruction({ op: "local.set", index: errTmp });
511
- this.pushInstruction({ op: "br", depth: 2 });
512
- this.pushInstruction("end");
513
-
514
- this.pushInstruction("end"); // end if nr > 0
515
-
516
- // if readErr != nil:
517
- this.pushInstruction({ op: "local.get", index: readErrTmp });
518
- this.pushInstruction("ref.is_null");
519
- this.pushInstruction("i32.eqz");
520
- this.pushInstruction({ op: "if", blockType: "void" });
521
- this.pushInstruction({ op: "local.get", index: readErrTmp });
522
- this.emitIoConst("EOF", "anyref");
523
- this.pushInstruction({
524
- op: "call",
525
- funcIndex: this.mod.resolveFuncIndex("__errors_is"),
526
- });
527
- this.pushInstruction({ op: "if", blockType: "void" });
528
- this.pushInstruction({ op: "ref.null", heapType: "any" });
529
- this.pushInstruction({ op: "local.set", index: errTmp });
530
- this.pushInstruction("else");
531
- this.pushInstruction({ op: "local.get", index: readErrTmp });
532
- this.pushInstruction({ op: "local.set", index: errTmp });
533
- this.pushInstruction("end");
534
- this.pushInstruction({ op: "br", depth: 2 }); // break loop
535
- this.pushInstruction("end"); // end if readErr != nil
536
-
537
- this.pushInstruction({ op: "br", depth: 0 }); // continue
538
- this.pushInstruction("end"); // end loop
539
- this.pushInstruction("end"); // end block
540
-
541
- this.pushInstruction({ op: "local.get", index: totalWrittenTmp });
542
- this.pushInstruction({ op: "local.get", index: errTmp });
543
-
544
- this.releaseTemp(nwTmp, "i64");
545
- this.releaseTemp(writeErrTmp, "anyref");
546
- this.releaseTemp(subsliceTmp, sliceW);
547
- this.releaseTemp(nrI32Tmp, "i32");
548
- this.releaseTemp(readErrTmp, "anyref");
549
- this.releaseTemp(errTmp, "anyref");
550
- this.releaseTemp(totalWrittenTmp, "i64");
551
- this.releaseTemp(bufTmp, sliceW);
552
- this.releaseTemp(bufArrTmp, arrW);
553
- }
554
-
555
- _emitAppendSliceBytes(dstSliceTmp, srcSliceTmp, countTmp, sliceInfo, arrW) {
556
- const arrInfo = sliceInfo.arrInfo;
557
- const byteGo = { kind: "basic", name: "byte" };
558
-
559
- const oldArrTmp = this.acquireTemp(arrW);
560
- const oldOffTmp = this.acquireTemp("i32");
561
- const oldLenTmp = this.acquireTemp("i32");
562
- const oldCapTmp = this.acquireTemp("i32");
563
- this._emitSliceUnpack(dstSliceTmp, sliceInfo, {
564
- arr: oldArrTmp,
565
- off: oldOffTmp,
566
- len: oldLenTmp,
567
- cap: oldCapTmp,
568
- });
569
-
570
- const newLenTmp = this.acquireTemp("i32");
571
- this.pushInstruction({ op: "local.get", index: oldLenTmp });
572
- this.pushInstruction({ op: "local.get", index: countTmp });
573
- this.pushInstruction("i32.add");
574
- this.pushInstruction({ op: "local.set", index: newLenTmp });
575
-
576
- const newArrTmp = this.acquireTemp(arrW);
577
- const newOffTmp = this.acquireTemp("i32");
578
- const newCapTmp = this.acquireTemp("i32");
579
- this._emitGrowSlice({
580
- arrInfo,
581
- elemGoType: byteGo,
582
- oldArrTmp,
583
- oldOffTmp,
584
- oldLenTmp,
585
- oldCapTmp,
586
- newArrTmp,
587
- newOffTmp,
588
- newLenTmp,
589
- newCapTmp,
590
- });
591
-
592
- const srcArrTmp = this.acquireTemp(arrW);
593
- const srcOffTmp = this.acquireTemp("i32");
594
- const srcLenTmp = this.acquireTemp("i32");
595
- const srcCapTmp = this.acquireTemp("i32");
596
- this._emitSliceUnpack(srcSliceTmp, sliceInfo, {
597
- arr: srcArrTmp,
598
- off: srcOffTmp,
599
- len: srcLenTmp,
600
- cap: srcCapTmp,
601
- });
602
- this.releaseTemp(srcCapTmp, "i32");
603
- this.releaseTemp(srcLenTmp, "i32");
604
-
605
- this.pushInstruction({ op: "local.get", index: newArrTmp });
606
- this.pushInstruction({ op: "local.get", index: newOffTmp });
607
- this.pushInstruction({ op: "local.get", index: oldLenTmp });
608
- this.pushInstruction("i32.add");
609
- this.pushInstruction({ op: "local.get", index: srcArrTmp });
610
- this.pushInstruction({ op: "local.get", index: srcOffTmp });
611
- this.pushInstruction({ op: "local.get", index: countTmp });
612
- this._emitArrayCopy(arrInfo, byteGo);
613
-
614
- this.releaseTemp(srcOffTmp, "i32");
615
- this.releaseTemp(srcArrTmp, arrW);
616
-
617
- this.pushInstruction({ op: "local.get", index: newArrTmp });
618
- this.pushInstruction({ op: "local.get", index: newOffTmp });
619
- this.pushInstruction({ op: "local.get", index: newLenTmp });
620
- this.pushInstruction({ op: "local.get", index: newCapTmp });
621
- this.pushInstruction({
622
- op: "struct.new",
623
- typeIndex: sliceInfo.typeIndex,
624
- });
625
- this.pushInstruction({ op: "local.set", index: dstSliceTmp });
626
-
627
- this.releaseTemp(newCapTmp, "i32");
628
- this.releaseTemp(newOffTmp, "i32");
629
- this.releaseTemp(newArrTmp, arrW);
630
- this.releaseTemp(newLenTmp, "i32");
631
- this.releaseTemp(oldCapTmp, "i32");
632
- this.releaseTemp(oldLenTmp, "i32");
633
- this.releaseTemp(oldOffTmp, "i32");
634
- this.releaseTemp(oldArrTmp, arrW);
635
- }
636
-
637
- emitStringsNewReader(call, _targetWasmType) {
638
- const structInfo = this.mod.getStructType("strings.Reader");
639
- this.emitExpr(call.args[0], "externref");
640
- this._emitStringToByteSlice({ elem: { kind: "basic", name: "byte" } });
641
- this.pushInstruction({ op: "i64.const", value: 0n });
642
- if (structInfo.fields.length > 2) {
643
- this.pushInstruction({ op: "i64.const", value: -1n });
644
- }
645
- this.pushInstruction({
646
- op: "struct.new",
647
- typeIndex: structInfo.typeIndex,
648
- });
649
- }
650
-
651
- emitBytesNewReader(call, _targetWasmType) {
652
- const structInfo = this.mod.getStructType("bytes.Reader");
653
- const byteElemGo = { kind: "basic", name: "byte" };
654
- const sliceInfo = this.mod.getSliceType(byteElemGo);
655
- const sliceW = {
656
- kind: "ref",
657
- nullable: true,
658
- typeIndex: sliceInfo.typeIndex,
659
- };
660
- this.emitExpr(call.args[0], sliceW);
661
- this.pushInstruction({ op: "i64.const", value: 0n });
662
- if (structInfo.fields.length > 2) {
663
- this.pushInstruction({ op: "i64.const", value: -1n });
664
- }
665
- this.pushInstruction({
666
- op: "struct.new",
667
- typeIndex: structInfo.typeIndex,
668
- });
669
- }
670
-
671
- emitStringsReaderMethodCall(method, expr, args, targetWasmType) {
672
- if (method === "Read") {
673
- this._emitStringsReaderRead(expr, args);
674
- return;
675
- }
676
- if (method === "Len") {
677
- this._emitStringsReaderLen(expr, targetWasmType);
678
- return;
679
- }
680
- if (method === "Reset") {
681
- this._emitStringsReaderReset(expr, args);
682
- return;
683
- }
684
- if (method === "ReadAt") {
685
- this._emitReaderReadAt(expr, args, "strings.Reader");
686
- return;
687
- }
688
- if (method === "ReadByte") {
689
- this._emitReaderReadByte(expr, "strings.Reader");
690
- return;
691
- }
692
- if (method === "UnreadByte") {
693
- this._emitReaderUnreadByte(expr, "strings.Reader");
694
- return;
695
- }
696
- if (method === "ReadRune") {
697
- this._emitReaderReadRune(expr, "strings.Reader");
698
- return;
699
- }
700
- if (method === "UnreadRune") {
701
- this._emitReaderUnreadRune(expr, "strings.Reader");
702
- return;
703
- }
704
- if (method === "Seek") {
705
- this._emitReaderSeek(expr, args, "strings.Reader");
706
- return;
707
- }
708
- if (method === "Size") {
709
- this._emitReaderSize(expr, targetWasmType, "strings.Reader");
710
- return;
711
- }
712
- if (method === "WriteTo") {
713
- this._emitReaderWriteTo(expr, args, "strings.Reader");
714
- return;
715
- }
716
- throw new Error(`Unsupported strings.Reader method: ${method}`);
717
- }
718
-
719
- _emitStringsReaderRead(expr, args) {
720
- const structInfo = this.mod.getStructType("strings.Reader");
721
- const readerW = {
722
- kind: "ref",
723
- nullable: true,
724
- typeIndex: structInfo.typeIndex,
725
- };
726
- const rTmp = this.acquireTemp(readerW);
727
- this.emitExpr(expr, readerW);
728
- this.pushInstruction({ op: "local.set", index: rTmp });
729
-
730
- const byteElemGo = { kind: "basic", name: "byte" };
731
- const sliceInfo = this.mod.getSliceType(byteElemGo);
732
- const sliceW = {
733
- kind: "ref",
734
- nullable: true,
735
- typeIndex: sliceInfo.typeIndex,
736
- };
737
- const pTmp = this.acquireTemp(sliceW);
738
- this.emitExpr(args[0], sliceW);
739
- this.pushInstruction({ op: "local.set", index: pTmp });
740
-
741
- this._emitStringsReaderReadCore(rTmp, pTmp);
742
- this.releaseTemp(pTmp, sliceW);
743
- this.releaseTemp(rTmp, readerW);
744
- }
745
-
746
- _emitReaderReadCore(typeName, rTmp, pTmp) {
747
- const structInfo = this.mod.getStructType(typeName);
748
- const byteElemGo = { kind: "basic", name: "byte" };
749
- const sliceInfo = this.mod.getSliceType(byteElemGo);
750
- const arrW = {
751
- kind: "ref",
752
- nullable: true,
753
- typeIndex: sliceInfo.arrInfo.typeIndex,
754
- };
755
-
756
- const pArrTmp = this.acquireTemp(arrW);
757
- const pOffTmp = this.acquireTemp("i32");
758
- const pLenTmp = this.acquireTemp("i32");
759
- const pCapTmp = this.acquireTemp("i32");
760
- this._emitSliceUnpack(pTmp, sliceInfo, {
761
- arr: pArrTmp,
762
- off: pOffTmp,
763
- len: pLenTmp,
764
- cap: pCapTmp,
765
- });
766
- this.releaseTemp(pCapTmp, "i32");
767
-
768
- const resNTmp = this.acquireTemp("i64");
769
- const resErrTmp = this.acquireTemp("anyref");
770
-
771
- // if p.len == 0: (0, nil)
772
- this.pushInstruction({ op: "local.get", index: pLenTmp });
773
- this.pushInstruction("i32.eqz");
774
- this.pushInstruction({ op: "if", blockType: "void" });
775
- this.pushInstruction({ op: "i64.const", value: 0n });
776
- this.pushInstruction({ op: "local.set", index: resNTmp });
777
- this.pushInstruction({ op: "ref.null", heapType: "any" });
778
- this.pushInstruction({ op: "local.set", index: resErrTmp });
779
- this.pushInstruction("else");
780
-
781
- const srcSliceW = {
782
- kind: "ref",
783
- nullable: true,
784
- typeIndex: sliceInfo.typeIndex,
785
- };
786
- const srcSliceTmp = this.acquireTemp(srcSliceW);
787
- this.pushInstruction({ op: "local.get", index: rTmp });
788
- this.pushInstruction({
789
- op: "struct.get",
790
- typeIndex: structInfo.typeIndex,
791
- fieldIndex: 0,
792
- });
793
- this.pushInstruction({ op: "local.set", index: srcSliceTmp });
794
-
795
- const srcArrTmp = this.acquireTemp(arrW);
796
- const srcOffTmp = this.acquireTemp("i32");
797
- const srcLenTmp = this.acquireTemp("i32");
798
- const srcCapTmp = this.acquireTemp("i32");
799
- this._emitSliceUnpack(srcSliceTmp, sliceInfo, {
800
- arr: srcArrTmp,
801
- off: srcOffTmp,
802
- len: srcLenTmp,
803
- cap: srcCapTmp,
804
- });
805
- this.releaseTemp(srcCapTmp, "i32");
806
- this.releaseTemp(srcSliceTmp, srcSliceW);
807
-
808
- const posTmp = this.acquireTemp("i64");
809
- this.pushInstruction({ op: "local.get", index: rTmp });
810
- this.pushInstruction({
811
- op: "struct.get",
812
- typeIndex: structInfo.typeIndex,
813
- fieldIndex: 1,
814
- });
815
- this.pushInstruction({ op: "local.set", index: posTmp });
816
-
817
- // if pos >= srcLen: (0, io.EOF)
818
- this.pushInstruction({ op: "local.get", index: posTmp });
819
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
820
- this.pushInstruction("i64.extend_i32_u");
821
- this.pushInstruction("i64.ge_s");
822
- this.pushInstruction({ op: "if", blockType: "void" });
823
- this.pushInstruction({ op: "i64.const", value: 0n });
824
- this.pushInstruction({ op: "local.set", index: resNTmp });
825
- this.emitIoConst("EOF", "anyref");
826
- this.pushInstruction({ op: "local.set", index: resErrTmp });
827
- this.pushInstruction("else");
828
-
829
- // avail = srcLen - pos
830
- const availTmp = this.acquireTemp("i32");
831
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
832
- this.pushInstruction({ op: "local.get", index: posTmp });
833
- this.pushInstruction("i32.wrap_i64");
834
- this.pushInstruction("i32.sub");
835
- this.pushInstruction({ op: "local.set", index: availTmp });
836
-
837
- // n = min(p.len, avail)
838
- const nTmp = this.acquireTemp("i32");
839
- this.pushInstruction({ op: "local.get", index: pLenTmp });
840
- this.pushInstruction({ op: "local.get", index: availTmp });
841
- this.pushInstruction("i32.lt_s");
842
- this.pushInstruction({ op: "if", blockType: "i32" });
843
- this.pushInstruction({ op: "local.get", index: pLenTmp });
844
- this.pushInstruction("else");
845
- this.pushInstruction({ op: "local.get", index: availTmp });
846
- this.pushInstruction("end");
847
- this.pushInstruction({ op: "local.set", index: nTmp });
848
-
849
- // copy bytes: p.arr[p.off] = src.arr[src.off + pos]
850
- this.pushInstruction({ op: "local.get", index: pArrTmp });
851
- this.pushInstruction({ op: "local.get", index: pOffTmp });
852
- this.pushInstruction({ op: "local.get", index: srcArrTmp });
853
- this.pushInstruction({ op: "local.get", index: srcOffTmp });
854
- this.pushInstruction({ op: "local.get", index: posTmp });
855
- this.pushInstruction("i32.wrap_i64");
856
- this.pushInstruction("i32.add");
857
- this.pushInstruction({ op: "local.get", index: nTmp });
858
- this._emitArrayCopy(sliceInfo.arrInfo, byteElemGo);
859
-
860
- // r._pos += n
861
- this.pushInstruction({ op: "local.get", index: rTmp });
862
- this.pushInstruction({ op: "local.get", index: posTmp });
863
- this.pushInstruction({ op: "local.get", index: nTmp });
864
- this.pushInstruction("i64.extend_i32_u");
865
- this.pushInstruction("i64.add");
866
- this.pushInstruction({
867
- op: "struct.set",
868
- typeIndex: structInfo.typeIndex,
869
- fieldIndex: 1,
870
- });
871
-
872
- if (structInfo.fields.length > 2) {
873
- this.pushInstruction({ op: "local.get", index: rTmp });
874
- this.pushInstruction({ op: "i64.const", value: -1n });
875
- this.pushInstruction({
876
- op: "struct.set",
877
- typeIndex: structInfo.typeIndex,
878
- fieldIndex: 2,
879
- });
880
- }
881
-
882
- this.pushInstruction({ op: "local.get", index: nTmp });
883
- this.pushInstruction("i64.extend_i32_u");
884
- this.pushInstruction({ op: "local.set", index: resNTmp });
885
- this.pushInstruction({ op: "ref.null", heapType: "any" });
886
- this.pushInstruction({ op: "local.set", index: resErrTmp });
887
-
888
- this.releaseTemp(nTmp, "i32");
889
- this.releaseTemp(availTmp, "i32");
890
- this.pushInstruction("end");
891
- this.releaseTemp(posTmp, "i64");
892
- this.releaseTemp(srcLenTmp, "i32");
893
- this.releaseTemp(srcOffTmp, "i32");
894
- this.releaseTemp(srcArrTmp, arrW);
895
- this.pushInstruction("end");
896
-
897
- this.pushInstruction({ op: "local.get", index: resNTmp });
898
- this.pushInstruction({ op: "local.get", index: resErrTmp });
899
-
900
- this.releaseTemp(resErrTmp, "anyref");
901
- this.releaseTemp(resNTmp, "i64");
902
- this.releaseTemp(pLenTmp, "i32");
903
- this.releaseTemp(pOffTmp, "i32");
904
- this.releaseTemp(pArrTmp, arrW);
905
- }
906
-
907
- _emitReaderLenCore(typeName, rTmp, targetWasmType) {
908
- const structInfo = this.mod.getStructType(typeName);
909
- const byteElemGo = { kind: "basic", name: "byte" };
910
- const sliceInfo = this.mod.getSliceType(byteElemGo);
911
-
912
- this.pushInstruction({ op: "local.get", index: rTmp });
913
- this.pushInstruction({
914
- op: "struct.get",
915
- typeIndex: structInfo.typeIndex,
916
- fieldIndex: 0,
917
- });
918
- this.pushInstruction({
919
- op: "struct.get",
920
- typeIndex: sliceInfo.typeIndex,
921
- fieldIndex: 2,
922
- });
923
- this.pushInstruction("i64.extend_i32_u");
924
- this.pushInstruction({ op: "local.get", index: rTmp });
925
- this.pushInstruction({
926
- op: "struct.get",
927
- typeIndex: structInfo.typeIndex,
928
- fieldIndex: 1,
929
- });
930
- this.pushInstruction("i64.sub");
931
- const resTmp = this.acquireTemp("i64");
932
- this.pushInstruction({ op: "local.set", index: resTmp });
933
-
934
- this.pushInstruction({ op: "local.get", index: resTmp });
935
- this.pushInstruction({ op: "i64.const", value: 0n });
936
- this.pushInstruction("i64.lt_s");
937
- this.pushInstruction({ op: "if", blockType: "i64" });
938
- this.pushInstruction({ op: "i64.const", value: 0n });
939
- this.pushInstruction("else");
940
- this.pushInstruction({ op: "local.get", index: resTmp });
941
- this.pushInstruction("end");
942
- if ((targetWasmType ?? "i64") === "i32") {
943
- this.pushInstruction("i32.wrap_i64");
944
- }
945
- this.releaseTemp(resTmp, "i64");
946
- }
947
-
948
- _emitStringsReaderReadCore(rTmp, pTmp) {
949
- this._emitReaderReadCore("strings.Reader", rTmp, pTmp);
950
- }
951
-
952
- _emitStringsReaderLen(expr, targetWasmType) {
953
- const structInfo = this.mod.getStructType("strings.Reader");
954
- const readerW = {
955
- kind: "ref",
956
- nullable: true,
957
- typeIndex: structInfo.typeIndex,
958
- };
959
- const rTmp = this.acquireTemp(readerW);
960
- this.emitExpr(expr, readerW);
961
- this.pushInstruction({ op: "local.set", index: rTmp });
962
-
963
- this._emitStringsReaderLenCore(rTmp, targetWasmType);
964
- this.releaseTemp(rTmp, readerW);
965
- }
966
-
967
- _emitStringsReaderLenCore(rTmp, targetWasmType) {
968
- this._emitReaderLenCore("strings.Reader", rTmp, targetWasmType);
969
- }
970
-
971
- _emitStringsReaderReset(expr, args) {
972
- const structInfo = this.mod.getStructType("strings.Reader");
973
- const readerW = {
974
- kind: "ref",
975
- nullable: true,
976
- typeIndex: structInfo.typeIndex,
977
- };
978
- const rTmp = this.acquireTemp(readerW);
979
- this.emitExpr(expr, readerW);
980
- this.pushInstruction({ op: "local.set", index: rTmp });
981
-
982
- const sTmp = this.acquireTemp("externref");
983
- this.emitExpr(args[0], "externref");
984
- this.pushInstruction({ op: "local.set", index: sTmp });
985
-
986
- this._emitStringsReaderResetCore(rTmp, sTmp);
987
- this.releaseTemp(sTmp, "externref");
988
- this.releaseTemp(rTmp, readerW);
989
- }
990
-
991
- _emitStringsReaderResetCore(rTmp, sTmp) {
992
- const structInfo = this.mod.getStructType("strings.Reader");
993
- this.pushInstruction({ op: "local.get", index: rTmp });
994
- this.pushInstruction({ op: "local.get", index: sTmp });
995
- this._emitStringToByteSlice({ elem: { kind: "basic", name: "byte" } });
996
- this.pushInstruction({
997
- op: "struct.set",
998
- typeIndex: structInfo.typeIndex,
999
- fieldIndex: 0,
1000
- });
1001
- this.pushInstruction({ op: "local.get", index: rTmp });
1002
- this.pushInstruction({ op: "i64.const", value: 0n });
1003
- this.pushInstruction({
1004
- op: "struct.set",
1005
- typeIndex: structInfo.typeIndex,
1006
- fieldIndex: 1,
1007
- });
1008
- if (structInfo.fields.length > 2) {
1009
- this.pushInstruction({ op: "local.get", index: rTmp });
1010
- this.pushInstruction({ op: "i64.const", value: -1n });
1011
- this.pushInstruction({
1012
- op: "struct.set",
1013
- typeIndex: structInfo.typeIndex,
1014
- fieldIndex: 2,
1015
- });
1016
- }
1017
- }
1018
-
1019
- emitBytesReaderMethodCall(method, expr, args, targetWasmType) {
1020
- if (method === "Read") {
1021
- this._emitBytesReaderRead(expr, args);
1022
- return;
1023
- }
1024
- if (method === "Len") {
1025
- this._emitBytesReaderLen(expr, targetWasmType);
1026
- return;
1027
- }
1028
- if (method === "Reset") {
1029
- this._emitBytesReaderReset(expr, args);
1030
- return;
1031
- }
1032
- if (method === "ReadAt") {
1033
- this._emitReaderReadAt(expr, args, "bytes.Reader");
1034
- return;
1035
- }
1036
- if (method === "ReadByte") {
1037
- this._emitReaderReadByte(expr, "bytes.Reader");
1038
- return;
1039
- }
1040
- if (method === "UnreadByte") {
1041
- this._emitReaderUnreadByte(expr, "bytes.Reader");
1042
- return;
1043
- }
1044
- if (method === "ReadRune") {
1045
- this._emitReaderReadRune(expr, "bytes.Reader");
1046
- return;
1047
- }
1048
- if (method === "UnreadRune") {
1049
- this._emitReaderUnreadRune(expr, "bytes.Reader");
1050
- return;
1051
- }
1052
- if (method === "Seek") {
1053
- this._emitReaderSeek(expr, args, "bytes.Reader");
1054
- return;
1055
- }
1056
- if (method === "Size") {
1057
- this._emitReaderSize(expr, targetWasmType, "bytes.Reader");
1058
- return;
1059
- }
1060
- if (method === "WriteTo") {
1061
- this._emitReaderWriteTo(expr, args, "bytes.Reader");
1062
- return;
1063
- }
1064
- throw new Error(`Unsupported bytes.Reader method: ${method}`);
1065
- }
1066
-
1067
- _emitBytesReaderRead(expr, args) {
1068
- const structInfo = this.mod.getStructType("bytes.Reader");
1069
- const readerW = {
1070
- kind: "ref",
1071
- nullable: true,
1072
- typeIndex: structInfo.typeIndex,
1073
- };
1074
- const rTmp = this.acquireTemp(readerW);
1075
- this.emitExpr(expr, readerW);
1076
- this.pushInstruction({ op: "local.set", index: rTmp });
1077
-
1078
- const byteElemGo = { kind: "basic", name: "byte" };
1079
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1080
- const sliceW = {
1081
- kind: "ref",
1082
- nullable: true,
1083
- typeIndex: sliceInfo.typeIndex,
1084
- };
1085
- const pTmp = this.acquireTemp(sliceW);
1086
- this.emitExpr(args[0], sliceW);
1087
- this.pushInstruction({ op: "local.set", index: pTmp });
1088
-
1089
- this._emitBytesReaderReadCore(rTmp, pTmp);
1090
- this.releaseTemp(pTmp, sliceW);
1091
- this.releaseTemp(rTmp, readerW);
1092
- }
1093
-
1094
- _emitBytesReaderReadCore(rTmp, pTmp) {
1095
- this._emitReaderReadCore("bytes.Reader", rTmp, pTmp);
1096
- }
1097
-
1098
- _emitBytesReaderLen(expr, targetWasmType) {
1099
- const structInfo = this.mod.getStructType("bytes.Reader");
1100
- const readerW = {
1101
- kind: "ref",
1102
- nullable: true,
1103
- typeIndex: structInfo.typeIndex,
1104
- };
1105
- const rTmp = this.acquireTemp(readerW);
1106
- this.emitExpr(expr, readerW);
1107
- this.pushInstruction({ op: "local.set", index: rTmp });
1108
-
1109
- this._emitBytesReaderLenCore(rTmp, targetWasmType);
1110
- this.releaseTemp(rTmp, readerW);
1111
- }
1112
-
1113
- _emitBytesReaderLenCore(rTmp, targetWasmType) {
1114
- this._emitReaderLenCore("bytes.Reader", rTmp, targetWasmType);
1115
- }
1116
-
1117
- _emitBytesReaderReset(expr, args) {
1118
- const structInfo = this.mod.getStructType("bytes.Reader");
1119
- const readerW = {
1120
- kind: "ref",
1121
- nullable: true,
1122
- typeIndex: structInfo.typeIndex,
1123
- };
1124
- const rTmp = this.acquireTemp(readerW);
1125
- this.emitExpr(expr, readerW);
1126
- this.pushInstruction({ op: "local.set", index: rTmp });
1127
-
1128
- const byteElemGo = { kind: "basic", name: "byte" };
1129
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1130
- const sliceW = {
1131
- kind: "ref",
1132
- nullable: true,
1133
- typeIndex: sliceInfo.typeIndex,
1134
- };
1135
- const bTmp = this.acquireTemp(sliceW);
1136
- this.emitExpr(args[0], sliceW);
1137
- this.pushInstruction({ op: "local.set", index: bTmp });
1138
-
1139
- this._emitBytesReaderResetCore(rTmp, bTmp);
1140
- this.releaseTemp(bTmp, sliceW);
1141
- this.releaseTemp(rTmp, readerW);
1142
- }
1143
-
1144
- _emitBytesReaderResetCore(rTmp, bTmp) {
1145
- const structInfo = this.mod.getStructType("bytes.Reader");
1146
- this.pushInstruction({ op: "local.get", index: rTmp });
1147
- this.pushInstruction({ op: "local.get", index: bTmp });
1148
- this.pushInstruction({
1149
- op: "struct.set",
1150
- typeIndex: structInfo.typeIndex,
1151
- fieldIndex: 0,
1152
- });
1153
- this.pushInstruction({ op: "local.get", index: rTmp });
1154
- this.pushInstruction({ op: "i64.const", value: 0n });
1155
- this.pushInstruction({
1156
- op: "struct.set",
1157
- typeIndex: structInfo.typeIndex,
1158
- fieldIndex: 1,
1159
- });
1160
- if (structInfo.fields.length > 2) {
1161
- this.pushInstruction({ op: "local.get", index: rTmp });
1162
- this.pushInstruction({ op: "i64.const", value: -1n });
1163
- this.pushInstruction({
1164
- op: "struct.set",
1165
- typeIndex: structInfo.typeIndex,
1166
- fieldIndex: 2,
1167
- });
1168
- }
1169
- }
1170
-
1171
- _emitNewError(msg) {
1172
- const strIdx = this.mod.internString(msg);
1173
- this.pushInstruction({ op: "i32.const", value: strIdx });
1174
- this.pushInstruction({
1175
- op: "call",
1176
- funcIndex: this.mod.getStringImportIndex(),
1177
- });
1178
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1179
- this.pushInstruction({
1180
- op: "call",
1181
- funcIndex: this.mod.resolveFuncIndex("__mk_error"),
1182
- });
1183
- }
1184
-
1185
- _emitReaderReadAt(expr, args, typeName) {
1186
- const structInfo = this.mod.getStructType(typeName);
1187
- const readerW = {
1188
- kind: "ref",
1189
- nullable: true,
1190
- typeIndex: structInfo.typeIndex,
1191
- };
1192
- const rTmp = this.acquireTemp(readerW);
1193
- this.emitExpr(expr, readerW);
1194
- this.pushInstruction({ op: "local.set", index: rTmp });
1195
-
1196
- const byteElemGo = { kind: "basic", name: "byte" };
1197
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1198
- const arrW = {
1199
- kind: "ref",
1200
- nullable: true,
1201
- typeIndex: sliceInfo.arrInfo.typeIndex,
1202
- };
1203
- const sliceW = {
1204
- kind: "ref",
1205
- nullable: true,
1206
- typeIndex: sliceInfo.typeIndex,
1207
- };
1208
-
1209
- const pTmp = this.acquireTemp(sliceW);
1210
- this.emitExpr(args[0], sliceW);
1211
- this.pushInstruction({ op: "local.set", index: pTmp });
1212
-
1213
- const offTmp = this.acquireTemp("i64");
1214
- this.emitExpr(args[1], "i64");
1215
- this.pushInstruction({ op: "local.set", index: offTmp });
1216
-
1217
- const pArrTmp = this.acquireTemp(arrW);
1218
- const pOffTmp = this.acquireTemp("i32");
1219
- const pLenTmp = this.acquireTemp("i32");
1220
- const pCapTmp = this.acquireTemp("i32");
1221
- this._emitSliceUnpack(pTmp, sliceInfo, {
1222
- arr: pArrTmp,
1223
- off: pOffTmp,
1224
- len: pLenTmp,
1225
- cap: pCapTmp,
1226
- });
1227
- this.releaseTemp(pCapTmp, "i32");
1228
-
1229
- const srcSliceTmp = this.acquireTemp(sliceW);
1230
- this.pushInstruction({ op: "local.get", index: rTmp });
1231
- this.pushInstruction({
1232
- op: "struct.get",
1233
- typeIndex: structInfo.typeIndex,
1234
- fieldIndex: 0,
1235
- });
1236
- this.pushInstruction({ op: "local.set", index: srcSliceTmp });
1237
-
1238
- const srcArrTmp = this.acquireTemp(arrW);
1239
- const srcOffTmp = this.acquireTemp("i32");
1240
- const srcLenTmp = this.acquireTemp("i32");
1241
- const srcCapTmp = this.acquireTemp("i32");
1242
- this._emitSliceUnpack(srcSliceTmp, sliceInfo, {
1243
- arr: srcArrTmp,
1244
- off: srcOffTmp,
1245
- len: srcLenTmp,
1246
- cap: srcCapTmp,
1247
- });
1248
- this.releaseTemp(srcCapTmp, "i32");
1249
- this.releaseTemp(srcSliceTmp, sliceW);
1250
-
1251
- const resNTmp = this.acquireTemp("i64");
1252
- const resErrTmp = this.acquireTemp("anyref");
1253
-
1254
- // if off < 0: return (0, errors.New("<typeName>.ReadAt: negative offset"))
1255
- this.pushInstruction({ op: "local.get", index: offTmp });
1256
- this.pushInstruction({ op: "i64.const", value: 0n });
1257
- this.pushInstruction("i64.lt_s");
1258
- this.pushInstruction({ op: "if", blockType: "void" });
1259
- this.pushInstruction({ op: "i64.const", value: 0n });
1260
- this.pushInstruction({ op: "local.set", index: resNTmp });
1261
- this._emitNewError(`${typeName}.ReadAt: negative offset`);
1262
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1263
- this.pushInstruction("else");
1264
-
1265
- // if off >= srcLen: return (0, io.EOF)
1266
- this.pushInstruction({ op: "local.get", index: offTmp });
1267
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
1268
- this.pushInstruction("i64.extend_i32_u");
1269
- this.pushInstruction("i64.ge_s");
1270
- this.pushInstruction({ op: "if", blockType: "void" });
1271
- this.pushInstruction({ op: "i64.const", value: 0n });
1272
- this.pushInstruction({ op: "local.set", index: resNTmp });
1273
- this.emitIoConst("EOF", "anyref");
1274
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1275
- this.pushInstruction("else");
1276
-
1277
- // avail = srcLen - int(off)
1278
- const availTmp = this.acquireTemp("i32");
1279
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
1280
- this.pushInstruction({ op: "local.get", index: offTmp });
1281
- this.pushInstruction("i32.wrap_i64");
1282
- this.pushInstruction("i32.sub");
1283
- this.pushInstruction({ op: "local.set", index: availTmp });
1284
-
1285
- // n = min(pLen, avail)
1286
- const nTmp = this.acquireTemp("i32");
1287
- this.pushInstruction({ op: "local.get", index: pLenTmp });
1288
- this.pushInstruction({ op: "local.get", index: availTmp });
1289
- this.pushInstruction("i32.lt_s");
1290
- this.pushInstruction({ op: "if", blockType: "i32" });
1291
- this.pushInstruction({ op: "local.get", index: pLenTmp });
1292
- this.pushInstruction("else");
1293
- this.pushInstruction({ op: "local.get", index: availTmp });
1294
- this.pushInstruction("end");
1295
- this.pushInstruction({ op: "local.set", index: nTmp });
1296
-
1297
- // copy bytes: pArr[pOff] = srcArr[srcOff + off]
1298
- this.pushInstruction({ op: "local.get", index: pArrTmp });
1299
- this.pushInstruction({ op: "local.get", index: pOffTmp });
1300
- this.pushInstruction({ op: "local.get", index: srcArrTmp });
1301
- this.pushInstruction({ op: "local.get", index: srcOffTmp });
1302
- this.pushInstruction({ op: "local.get", index: offTmp });
1303
- this.pushInstruction("i32.wrap_i64");
1304
- this.pushInstruction("i32.add");
1305
- this.pushInstruction({ op: "local.get", index: nTmp });
1306
- this._emitArrayCopy(sliceInfo.arrInfo, byteElemGo);
1307
-
1308
- this.pushInstruction({ op: "local.get", index: nTmp });
1309
- this.pushInstruction("i64.extend_i32_u");
1310
- this.pushInstruction({ op: "local.set", index: resNTmp });
1311
-
1312
- // if n < pLen: io.EOF else nil
1313
- this.pushInstruction({ op: "local.get", index: nTmp });
1314
- this.pushInstruction({ op: "local.get", index: pLenTmp });
1315
- this.pushInstruction("i32.lt_s");
1316
- this.pushInstruction({ op: "if", blockType: "anyref" });
1317
- this.emitIoConst("EOF", "anyref");
1318
- this.pushInstruction("else");
1319
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1320
- this.pushInstruction("end");
1321
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1322
-
1323
- this.releaseTemp(nTmp, "i32");
1324
- this.releaseTemp(availTmp, "i32");
1325
- this.pushInstruction("end");
1326
- this.pushInstruction("end");
1327
-
1328
- this.pushInstruction({ op: "local.get", index: resNTmp });
1329
- this.pushInstruction({ op: "local.get", index: resErrTmp });
1330
-
1331
- this.releaseTemp(resErrTmp, "anyref");
1332
- this.releaseTemp(resNTmp, "i64");
1333
- this.releaseTemp(srcLenTmp, "i32");
1334
- this.releaseTemp(srcOffTmp, "i32");
1335
- this.releaseTemp(srcArrTmp, arrW);
1336
- this.releaseTemp(pLenTmp, "i32");
1337
- this.releaseTemp(pOffTmp, "i32");
1338
- this.releaseTemp(pArrTmp, arrW);
1339
- this.releaseTemp(offTmp, "i64");
1340
- this.releaseTemp(pTmp, sliceW);
1341
- this.releaseTemp(rTmp, readerW);
1342
- }
1343
-
1344
- _emitReaderReadByte(expr, typeName) {
1345
- const structInfo = this.mod.getStructType(typeName);
1346
- const readerW = {
1347
- kind: "ref",
1348
- nullable: true,
1349
- typeIndex: structInfo.typeIndex,
1350
- };
1351
- const rTmp = this.acquireTemp(readerW);
1352
- this.emitExpr(expr, readerW);
1353
- this.pushInstruction({ op: "local.set", index: rTmp });
1354
-
1355
- const byteElemGo = { kind: "basic", name: "byte" };
1356
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1357
- const arrW = {
1358
- kind: "ref",
1359
- nullable: true,
1360
- typeIndex: sliceInfo.arrInfo.typeIndex,
1361
- };
1362
- const sliceW = {
1363
- kind: "ref",
1364
- nullable: true,
1365
- typeIndex: sliceInfo.typeIndex,
1366
- };
1367
-
1368
- const srcSliceTmp = this.acquireTemp(sliceW);
1369
- this.pushInstruction({ op: "local.get", index: rTmp });
1370
- this.pushInstruction({
1371
- op: "struct.get",
1372
- typeIndex: structInfo.typeIndex,
1373
- fieldIndex: 0,
1374
- });
1375
- this.pushInstruction({ op: "local.set", index: srcSliceTmp });
1376
-
1377
- const srcArrTmp = this.acquireTemp(arrW);
1378
- const srcOffTmp = this.acquireTemp("i32");
1379
- const srcLenTmp = this.acquireTemp("i32");
1380
- const srcCapTmp = this.acquireTemp("i32");
1381
- this._emitSliceUnpack(srcSliceTmp, sliceInfo, {
1382
- arr: srcArrTmp,
1383
- off: srcOffTmp,
1384
- len: srcLenTmp,
1385
- cap: srcCapTmp,
1386
- });
1387
- this.releaseTemp(srcCapTmp, "i32");
1388
- this.releaseTemp(srcSliceTmp, sliceW);
1389
-
1390
- const posTmp = this.acquireTemp("i64");
1391
- this.pushInstruction({ op: "local.get", index: rTmp });
1392
- this.pushInstruction({
1393
- op: "struct.get",
1394
- typeIndex: structInfo.typeIndex,
1395
- fieldIndex: 1,
1396
- });
1397
- this.pushInstruction({ op: "local.set", index: posTmp });
1398
-
1399
- const resByteTmp = this.acquireTemp("i32");
1400
- const resErrTmp = this.acquireTemp("anyref");
1401
-
1402
- this.pushInstruction({ op: "local.get", index: posTmp });
1403
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
1404
- this.pushInstruction("i64.extend_i32_u");
1405
- this.pushInstruction("i64.ge_s");
1406
- this.pushInstruction({ op: "if", blockType: "void" });
1407
- this.pushInstruction({ op: "i32.const", value: 0 });
1408
- this.pushInstruction({ op: "local.set", index: resByteTmp });
1409
- this.emitIoConst("EOF", "anyref");
1410
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1411
- this.pushInstruction("else");
1412
-
1413
- this.pushInstruction({ op: "local.get", index: srcArrTmp });
1414
- this.pushInstruction({ op: "local.get", index: srcOffTmp });
1415
- this.pushInstruction({ op: "local.get", index: posTmp });
1416
- this.pushInstruction("i32.wrap_i64");
1417
- this.pushInstruction("i32.add");
1418
- this.pushInstruction({
1419
- op: "array.get",
1420
- typeIndex: sliceInfo.arrInfo.typeIndex,
1421
- });
1422
- this.pushInstruction({ op: "local.set", index: resByteTmp });
1423
-
1424
- this.pushInstruction({ op: "local.get", index: rTmp });
1425
- this.pushInstruction({ op: "local.get", index: posTmp });
1426
- this.pushInstruction({ op: "i64.const", value: 1n });
1427
- this.pushInstruction("i64.add");
1428
- this.pushInstruction({
1429
- op: "struct.set",
1430
- typeIndex: structInfo.typeIndex,
1431
- fieldIndex: 1,
1432
- });
1433
-
1434
- if (structInfo.fields.length > 2) {
1435
- this.pushInstruction({ op: "local.get", index: rTmp });
1436
- this.pushInstruction({ op: "i64.const", value: -1n });
1437
- this.pushInstruction({
1438
- op: "struct.set",
1439
- typeIndex: structInfo.typeIndex,
1440
- fieldIndex: 2,
1441
- });
1442
- }
1443
-
1444
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1445
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1446
- this.pushInstruction("end");
1447
-
1448
- this.pushInstruction({ op: "local.get", index: resByteTmp });
1449
- this.pushInstruction({ op: "local.get", index: resErrTmp });
1450
-
1451
- this.releaseTemp(resErrTmp, "anyref");
1452
- this.releaseTemp(resByteTmp, "i32");
1453
- this.releaseTemp(posTmp, "i64");
1454
- this.releaseTemp(srcLenTmp, "i32");
1455
- this.releaseTemp(srcOffTmp, "i32");
1456
- this.releaseTemp(srcArrTmp, arrW);
1457
- this.releaseTemp(rTmp, readerW);
1458
- }
1459
-
1460
- _emitReaderUnreadByte(expr, typeName) {
1461
- const structInfo = this.mod.getStructType(typeName);
1462
- const readerW = {
1463
- kind: "ref",
1464
- nullable: true,
1465
- typeIndex: structInfo.typeIndex,
1466
- };
1467
- const rTmp = this.acquireTemp(readerW);
1468
- this.emitExpr(expr, readerW);
1469
- this.pushInstruction({ op: "local.set", index: rTmp });
1470
-
1471
- const posTmp = this.acquireTemp("i64");
1472
- this.pushInstruction({ op: "local.get", index: rTmp });
1473
- this.pushInstruction({
1474
- op: "struct.get",
1475
- typeIndex: structInfo.typeIndex,
1476
- fieldIndex: 1,
1477
- });
1478
- this.pushInstruction({ op: "local.set", index: posTmp });
1479
-
1480
- const resErrTmp = this.acquireTemp("anyref");
1481
-
1482
- this.pushInstruction({ op: "local.get", index: posTmp });
1483
- this.pushInstruction({ op: "i64.const", value: 0n });
1484
- this.pushInstruction("i64.le_s");
1485
- this.pushInstruction({ op: "if", blockType: "void" });
1486
- const targetKind = typeName.startsWith("strings") ? "string" : "slice";
1487
- this._emitNewError(`${typeName}.UnreadByte: at beginning of ${targetKind}`);
1488
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1489
- this.pushInstruction("else");
1490
-
1491
- this.pushInstruction({ op: "local.get", index: rTmp });
1492
- this.pushInstruction({ op: "local.get", index: posTmp });
1493
- this.pushInstruction({ op: "i64.const", value: 1n });
1494
- this.pushInstruction("i64.sub");
1495
- this.pushInstruction({
1496
- op: "struct.set",
1497
- typeIndex: structInfo.typeIndex,
1498
- fieldIndex: 1,
1499
- });
1500
-
1501
- if (structInfo.fields.length > 2) {
1502
- this.pushInstruction({ op: "local.get", index: rTmp });
1503
- this.pushInstruction({ op: "i64.const", value: -1n });
1504
- this.pushInstruction({
1505
- op: "struct.set",
1506
- typeIndex: structInfo.typeIndex,
1507
- fieldIndex: 2,
1508
- });
1509
- }
1510
-
1511
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1512
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1513
- this.pushInstruction("end");
1514
-
1515
- this.pushInstruction({ op: "local.get", index: resErrTmp });
1516
-
1517
- this.releaseTemp(resErrTmp, "anyref");
1518
- this.releaseTemp(posTmp, "i64");
1519
- this.releaseTemp(rTmp, readerW);
1520
- }
1521
-
1522
- _emitReaderReadRune(expr, typeName) {
1523
- const structInfo = this.mod.getStructType(typeName);
1524
- const readerW = {
1525
- kind: "ref",
1526
- nullable: true,
1527
- typeIndex: structInfo.typeIndex,
1528
- };
1529
- const rTmp = this.acquireTemp(readerW);
1530
- this.emitExpr(expr, readerW);
1531
- this.pushInstruction({ op: "local.set", index: rTmp });
1532
-
1533
- const byteElemGo = { kind: "basic", name: "byte" };
1534
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1535
- const arrW = {
1536
- kind: "ref",
1537
- nullable: true,
1538
- typeIndex: sliceInfo.arrInfo.typeIndex,
1539
- };
1540
- const sliceW = {
1541
- kind: "ref",
1542
- nullable: true,
1543
- typeIndex: sliceInfo.typeIndex,
1544
- };
1545
-
1546
- const srcSliceTmp = this.acquireTemp(sliceW);
1547
- this.pushInstruction({ op: "local.get", index: rTmp });
1548
- this.pushInstruction({
1549
- op: "struct.get",
1550
- typeIndex: structInfo.typeIndex,
1551
- fieldIndex: 0,
1552
- });
1553
- this.pushInstruction({ op: "local.set", index: srcSliceTmp });
1554
-
1555
- const srcArrTmp = this.acquireTemp(arrW);
1556
- const srcOffTmp = this.acquireTemp("i32");
1557
- const srcLenTmp = this.acquireTemp("i32");
1558
- const srcCapTmp = this.acquireTemp("i32");
1559
- this._emitSliceUnpack(srcSliceTmp, sliceInfo, {
1560
- arr: srcArrTmp,
1561
- off: srcOffTmp,
1562
- len: srcLenTmp,
1563
- cap: srcCapTmp,
1564
- });
1565
- this.releaseTemp(srcCapTmp, "i32");
1566
- this.releaseTemp(srcSliceTmp, sliceW);
1567
-
1568
- const posTmp = this.acquireTemp("i64");
1569
- this.pushInstruction({ op: "local.get", index: rTmp });
1570
- this.pushInstruction({
1571
- op: "struct.get",
1572
- typeIndex: structInfo.typeIndex,
1573
- fieldIndex: 1,
1574
- });
1575
- this.pushInstruction({ op: "local.set", index: posTmp });
1576
-
1577
- const resRuneTmp = this.acquireTemp("i32");
1578
- const resSizeTmp = this.acquireTemp("i64");
1579
- const resErrTmp = this.acquireTemp("anyref");
1580
-
1581
- this.pushInstruction({ op: "local.get", index: posTmp });
1582
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
1583
- this.pushInstruction("i64.extend_i32_u");
1584
- this.pushInstruction("i64.ge_s");
1585
- this.pushInstruction({ op: "if", blockType: "void" });
1586
- if (structInfo.fields.length > 2) {
1587
- this.pushInstruction({ op: "local.get", index: rTmp });
1588
- this.pushInstruction({ op: "i64.const", value: -1n });
1589
- this.pushInstruction({
1590
- op: "struct.set",
1591
- typeIndex: structInfo.typeIndex,
1592
- fieldIndex: 2,
1593
- });
1594
- }
1595
- this.pushInstruction({ op: "i32.const", value: 0 });
1596
- this.pushInstruction({ op: "local.set", index: resRuneTmp });
1597
- this.pushInstruction({ op: "i64.const", value: 0n });
1598
- this.pushInstruction({ op: "local.set", index: resSizeTmp });
1599
- this.emitIoConst("EOF", "anyref");
1600
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1601
- this.pushInstruction("else");
1602
-
1603
- const cpTmp = this.acquireTemp("i32");
1604
- const runeLenTmp = this.acquireTemp("i32");
1605
- const posI32Tmp = this.acquireTemp("i32");
1606
- this.pushInstruction({ op: "local.get", index: posTmp });
1607
- this.pushInstruction("i32.wrap_i64");
1608
- this.pushInstruction({ op: "local.set", index: posI32Tmp });
1609
-
1610
- this._emitDecodeUtf8Rune({
1611
- arrTmp: srcArrTmp,
1612
- offTmp: srcOffTmp,
1613
- idxTmp: posI32Tmp,
1614
- lenTmp: srcLenTmp,
1615
- outRuneTmp: cpTmp,
1616
- outLenTmp: runeLenTmp,
1617
- arrTypeIndex: sliceInfo.arrInfo.typeIndex,
1618
- });
1619
-
1620
- if (structInfo.fields.length > 2) {
1621
- this.pushInstruction({ op: "local.get", index: rTmp });
1622
- this.pushInstruction({ op: "local.get", index: posTmp });
1623
- this.pushInstruction({
1624
- op: "struct.set",
1625
- typeIndex: structInfo.typeIndex,
1626
- fieldIndex: 2,
1627
- });
1628
- }
1629
-
1630
- this.pushInstruction({ op: "local.get", index: rTmp });
1631
- this.pushInstruction({ op: "local.get", index: posTmp });
1632
- this.pushInstruction({ op: "local.get", index: runeLenTmp });
1633
- this.pushInstruction("i64.extend_i32_u");
1634
- this.pushInstruction("i64.add");
1635
- this.pushInstruction({
1636
- op: "struct.set",
1637
- typeIndex: structInfo.typeIndex,
1638
- fieldIndex: 1,
1639
- });
1640
-
1641
- this.pushInstruction({ op: "local.get", index: cpTmp });
1642
- this.pushInstruction({ op: "local.set", index: resRuneTmp });
1643
- this.pushInstruction({ op: "local.get", index: runeLenTmp });
1644
- this.pushInstruction("i64.extend_i32_u");
1645
- this.pushInstruction({ op: "local.set", index: resSizeTmp });
1646
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1647
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1648
-
1649
- this.releaseTemp(posI32Tmp, "i32");
1650
- this.releaseTemp(runeLenTmp, "i32");
1651
- this.releaseTemp(cpTmp, "i32");
1652
- this.pushInstruction("end");
1653
-
1654
- this.pushInstruction({ op: "local.get", index: resRuneTmp });
1655
- this.pushInstruction({ op: "local.get", index: resSizeTmp });
1656
- this.pushInstruction({ op: "local.get", index: resErrTmp });
1657
-
1658
- this.releaseTemp(resErrTmp, "anyref");
1659
- this.releaseTemp(resSizeTmp, "i64");
1660
- this.releaseTemp(resRuneTmp, "i32");
1661
- this.releaseTemp(posTmp, "i64");
1662
- this.releaseTemp(srcLenTmp, "i32");
1663
- this.releaseTemp(srcOffTmp, "i32");
1664
- this.releaseTemp(srcArrTmp, arrW);
1665
- this.releaseTemp(rTmp, readerW);
1666
- }
1667
-
1668
- _emitReaderUnreadRune(expr, typeName) {
1669
- const structInfo = this.mod.getStructType(typeName);
1670
- const readerW = {
1671
- kind: "ref",
1672
- nullable: true,
1673
- typeIndex: structInfo.typeIndex,
1674
- };
1675
- const rTmp = this.acquireTemp(readerW);
1676
- this.emitExpr(expr, readerW);
1677
- this.pushInstruction({ op: "local.set", index: rTmp });
1678
-
1679
- const prevTmp = this.acquireTemp("i64");
1680
- if (structInfo.fields.length > 2) {
1681
- this.pushInstruction({ op: "local.get", index: rTmp });
1682
- this.pushInstruction({
1683
- op: "struct.get",
1684
- typeIndex: structInfo.typeIndex,
1685
- fieldIndex: 2,
1686
- });
1687
- this.pushInstruction({ op: "local.set", index: prevTmp });
1688
- } else {
1689
- this.pushInstruction({ op: "i64.const", value: -1n });
1690
- this.pushInstruction({ op: "local.set", index: prevTmp });
1691
- }
1692
-
1693
- const posTmp = this.acquireTemp("i64");
1694
- this.pushInstruction({ op: "local.get", index: rTmp });
1695
- this.pushInstruction({
1696
- op: "struct.get",
1697
- typeIndex: structInfo.typeIndex,
1698
- fieldIndex: 1,
1699
- });
1700
- this.pushInstruction({ op: "local.set", index: posTmp });
1701
-
1702
- const resErrTmp = this.acquireTemp("anyref");
1703
-
1704
- this.pushInstruction({ op: "local.get", index: prevTmp });
1705
- this.pushInstruction({ op: "i64.const", value: 0n });
1706
- this.pushInstruction("i64.lt_s");
1707
- this.pushInstruction({ op: "local.get", index: prevTmp });
1708
- this.pushInstruction({ op: "local.get", index: posTmp });
1709
- this.pushInstruction("i64.ge_s");
1710
- this.pushInstruction("i32.or");
1711
- this.pushInstruction({ op: "if", blockType: "void" });
1712
- this._emitNewError(
1713
- `${typeName}.UnreadRune: previous operation was not ReadRune`,
1714
- );
1715
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1716
- this.pushInstruction("else");
1717
-
1718
- this.pushInstruction({ op: "local.get", index: rTmp });
1719
- this.pushInstruction({ op: "local.get", index: prevTmp });
1720
- this.pushInstruction({
1721
- op: "struct.set",
1722
- typeIndex: structInfo.typeIndex,
1723
- fieldIndex: 1,
1724
- });
1725
-
1726
- if (structInfo.fields.length > 2) {
1727
- this.pushInstruction({ op: "local.get", index: rTmp });
1728
- this.pushInstruction({ op: "i64.const", value: -1n });
1729
- this.pushInstruction({
1730
- op: "struct.set",
1731
- typeIndex: structInfo.typeIndex,
1732
- fieldIndex: 2,
1733
- });
1734
- }
1735
-
1736
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1737
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1738
- this.pushInstruction("end");
1739
-
1740
- this.pushInstruction({ op: "local.get", index: resErrTmp });
1741
-
1742
- this.releaseTemp(resErrTmp, "anyref");
1743
- this.releaseTemp(posTmp, "i64");
1744
- this.releaseTemp(prevTmp, "i64");
1745
- this.releaseTemp(rTmp, readerW);
1746
- }
1747
-
1748
- _emitReaderSeek(expr, args, typeName) {
1749
- const structInfo = this.mod.getStructType(typeName);
1750
- const readerW = {
1751
- kind: "ref",
1752
- nullable: true,
1753
- typeIndex: structInfo.typeIndex,
1754
- };
1755
- const rTmp = this.acquireTemp(readerW);
1756
- this.emitExpr(expr, readerW);
1757
- this.pushInstruction({ op: "local.set", index: rTmp });
1758
-
1759
- const offTmp = this.acquireTemp("i64");
1760
- this.emitExpr(args[0], "i64");
1761
- this.pushInstruction({ op: "local.set", index: offTmp });
1762
-
1763
- const whenceTmp = this.acquireTemp("i32");
1764
- this._emitI32Arg(args[1]);
1765
- this.pushInstruction({ op: "local.set", index: whenceTmp });
1766
-
1767
- const byteElemGo = { kind: "basic", name: "byte" };
1768
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1769
- const sliceW = {
1770
- kind: "ref",
1771
- nullable: true,
1772
- typeIndex: sliceInfo.typeIndex,
1773
- };
1774
-
1775
- const srcSliceTmp = this.acquireTemp(sliceW);
1776
- this.pushInstruction({ op: "local.get", index: rTmp });
1777
- this.pushInstruction({
1778
- op: "struct.get",
1779
- typeIndex: structInfo.typeIndex,
1780
- fieldIndex: 0,
1781
- });
1782
- this.pushInstruction({ op: "local.set", index: srcSliceTmp });
1783
-
1784
- const srcLenTmp = this.acquireTemp("i32");
1785
- this.pushInstruction({ op: "local.get", index: srcSliceTmp });
1786
- this.pushInstruction({
1787
- op: "struct.get",
1788
- typeIndex: sliceInfo.typeIndex,
1789
- fieldIndex: 2,
1790
- });
1791
- this.pushInstruction({ op: "local.set", index: srcLenTmp });
1792
- this.releaseTemp(srcSliceTmp, sliceW);
1793
-
1794
- const posTmp = this.acquireTemp("i64");
1795
- this.pushInstruction({ op: "local.get", index: rTmp });
1796
- this.pushInstruction({
1797
- op: "struct.get",
1798
- typeIndex: structInfo.typeIndex,
1799
- fieldIndex: 1,
1800
- });
1801
- this.pushInstruction({ op: "local.set", index: posTmp });
1802
-
1803
- const newPosTmp = this.acquireTemp("i64");
1804
- const resErrTmp = this.acquireTemp("anyref");
1805
-
1806
- this.pushInstruction({ op: "local.get", index: whenceTmp });
1807
- this.pushInstruction({ op: "i32.const", value: 0 });
1808
- this.pushInstruction("i32.eq");
1809
- this.pushInstruction({ op: "if", blockType: "void" });
1810
- this.pushInstruction({ op: "local.get", index: offTmp });
1811
- this.pushInstruction({ op: "local.set", index: newPosTmp });
1812
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1813
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1814
- this.pushInstruction("else");
1815
-
1816
- this.pushInstruction({ op: "local.get", index: whenceTmp });
1817
- this.pushInstruction({ op: "i32.const", value: 1 });
1818
- this.pushInstruction("i32.eq");
1819
- this.pushInstruction({ op: "if", blockType: "void" });
1820
- this.pushInstruction({ op: "local.get", index: posTmp });
1821
- this.pushInstruction({ op: "local.get", index: offTmp });
1822
- this.pushInstruction("i64.add");
1823
- this.pushInstruction({ op: "local.set", index: newPosTmp });
1824
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1825
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1826
- this.pushInstruction("else");
1827
-
1828
- this.pushInstruction({ op: "local.get", index: whenceTmp });
1829
- this.pushInstruction({ op: "i32.const", value: 2 });
1830
- this.pushInstruction("i32.eq");
1831
- this.pushInstruction({ op: "if", blockType: "void" });
1832
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
1833
- this.pushInstruction("i64.extend_i32_u");
1834
- this.pushInstruction({ op: "local.get", index: offTmp });
1835
- this.pushInstruction("i64.add");
1836
- this.pushInstruction({ op: "local.set", index: newPosTmp });
1837
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1838
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1839
- this.pushInstruction("else");
1840
-
1841
- this.pushInstruction({ op: "i64.const", value: 0n });
1842
- this.pushInstruction({ op: "local.set", index: newPosTmp });
1843
- this._emitNewError(`${typeName}.Seek: invalid whence`);
1844
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1845
- this.pushInstruction("end");
1846
- this.pushInstruction("end");
1847
- this.pushInstruction("end");
1848
-
1849
- this.pushInstruction({ op: "local.get", index: resErrTmp });
1850
- this.pushInstruction("ref.is_null");
1851
- this.pushInstruction({ op: "if", blockType: "void" });
1852
- this.pushInstruction({ op: "local.get", index: newPosTmp });
1853
- this.pushInstruction({ op: "i64.const", value: 0n });
1854
- this.pushInstruction("i64.lt_s");
1855
- this.pushInstruction({ op: "if", blockType: "void" });
1856
- this.pushInstruction({ op: "i64.const", value: 0n });
1857
- this.pushInstruction({ op: "local.set", index: newPosTmp });
1858
- this._emitNewError(`${typeName}.Seek: negative position`);
1859
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1860
- this.pushInstruction("else");
1861
- this.pushInstruction({ op: "local.get", index: rTmp });
1862
- this.pushInstruction({ op: "local.get", index: newPosTmp });
1863
- this.pushInstruction({
1864
- op: "struct.set",
1865
- typeIndex: structInfo.typeIndex,
1866
- fieldIndex: 1,
1867
- });
1868
- if (structInfo.fields.length > 2) {
1869
- this.pushInstruction({ op: "local.get", index: rTmp });
1870
- this.pushInstruction({ op: "i64.const", value: -1n });
1871
- this.pushInstruction({
1872
- op: "struct.set",
1873
- typeIndex: structInfo.typeIndex,
1874
- fieldIndex: 2,
1875
- });
1876
- }
1877
- this.pushInstruction("end");
1878
- this.pushInstruction("end");
1879
-
1880
- this.pushInstruction({ op: "local.get", index: newPosTmp });
1881
- this.pushInstruction({ op: "local.get", index: resErrTmp });
1882
-
1883
- this.releaseTemp(resErrTmp, "anyref");
1884
- this.releaseTemp(newPosTmp, "i64");
1885
- this.releaseTemp(posTmp, "i64");
1886
- this.releaseTemp(srcLenTmp, "i32");
1887
- this.releaseTemp(whenceTmp, "i32");
1888
- this.releaseTemp(offTmp, "i64");
1889
- this.releaseTemp(rTmp, readerW);
1890
- }
1891
-
1892
- _emitReaderSize(expr, targetWasmType, typeName) {
1893
- const structInfo = this.mod.getStructType(typeName);
1894
- const readerW = {
1895
- kind: "ref",
1896
- nullable: true,
1897
- typeIndex: structInfo.typeIndex,
1898
- };
1899
- const rTmp = this.acquireTemp(readerW);
1900
- this.emitExpr(expr, readerW);
1901
- this.pushInstruction({ op: "local.set", index: rTmp });
1902
-
1903
- const byteElemGo = { kind: "basic", name: "byte" };
1904
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1905
- const sliceW = {
1906
- kind: "ref",
1907
- nullable: true,
1908
- typeIndex: sliceInfo.typeIndex,
1909
- };
1910
-
1911
- const srcSliceTmp = this.acquireTemp(sliceW);
1912
- this.pushInstruction({ op: "local.get", index: rTmp });
1913
- this.pushInstruction({
1914
- op: "struct.get",
1915
- typeIndex: structInfo.typeIndex,
1916
- fieldIndex: 0,
1917
- });
1918
- this.pushInstruction({ op: "local.set", index: srcSliceTmp });
1919
-
1920
- this.pushInstruction({ op: "local.get", index: srcSliceTmp });
1921
- this.pushInstruction({
1922
- op: "struct.get",
1923
- typeIndex: sliceInfo.typeIndex,
1924
- fieldIndex: 2,
1925
- });
1926
- this.pushInstruction("i64.extend_i32_u");
1927
-
1928
- if ((targetWasmType ?? "i64") === "i32") {
1929
- this.pushInstruction("i32.wrap_i64");
1930
- }
1931
-
1932
- this.releaseTemp(srcSliceTmp, sliceW);
1933
- this.releaseTemp(rTmp, readerW);
1934
- }
1935
-
1936
- _emitReaderWriteTo(expr, args, typeName) {
1937
- const structInfo = this.mod.getStructType(typeName);
1938
- const readerW = {
1939
- kind: "ref",
1940
- nullable: true,
1941
- typeIndex: structInfo.typeIndex,
1942
- };
1943
- const rTmp = this.acquireTemp(readerW);
1944
- this.emitExpr(expr, readerW);
1945
- this.pushInstruction({ op: "local.set", index: rTmp });
1946
-
1947
- const wTmp = this.acquireTemp("anyref");
1948
- this.emitExpr(args[0], "anyref");
1949
- this.pushInstruction({ op: "local.set", index: wTmp });
1950
-
1951
- const byteElemGo = { kind: "basic", name: "byte" };
1952
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1953
- const arrW = {
1954
- kind: "ref",
1955
- nullable: true,
1956
- typeIndex: sliceInfo.arrInfo.typeIndex,
1957
- };
1958
- const sliceW = {
1959
- kind: "ref",
1960
- nullable: true,
1961
- typeIndex: sliceInfo.typeIndex,
1962
- };
1963
-
1964
- const srcSliceTmp = this.acquireTemp(sliceW);
1965
- this.pushInstruction({ op: "local.get", index: rTmp });
1966
- this.pushInstruction({
1967
- op: "struct.get",
1968
- typeIndex: structInfo.typeIndex,
1969
- fieldIndex: 0,
1970
- });
1971
- this.pushInstruction({ op: "local.set", index: srcSliceTmp });
1972
-
1973
- const srcArrTmp = this.acquireTemp(arrW);
1974
- const srcOffTmp = this.acquireTemp("i32");
1975
- const srcLenTmp = this.acquireTemp("i32");
1976
- const srcCapTmp = this.acquireTemp("i32");
1977
- this._emitSliceUnpack(srcSliceTmp, sliceInfo, {
1978
- arr: srcArrTmp,
1979
- off: srcOffTmp,
1980
- len: srcLenTmp,
1981
- cap: srcCapTmp,
1982
- });
1983
- this.releaseTemp(srcSliceTmp, sliceW);
1984
-
1985
- const posTmp = this.acquireTemp("i64");
1986
- this.pushInstruction({ op: "local.get", index: rTmp });
1987
- this.pushInstruction({
1988
- op: "struct.get",
1989
- typeIndex: structInfo.typeIndex,
1990
- fieldIndex: 1,
1991
- });
1992
- this.pushInstruction({ op: "local.set", index: posTmp });
1993
-
1994
- const resNTmp = this.acquireTemp("i64");
1995
- const resErrTmp = this.acquireTemp("anyref");
1996
-
1997
- this.pushInstruction({ op: "local.get", index: posTmp });
1998
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
1999
- this.pushInstruction("i64.extend_i32_u");
2000
- this.pushInstruction("i64.ge_s");
2001
- this.pushInstruction({ op: "if", blockType: "void" });
2002
- this.pushInstruction({ op: "i64.const", value: 0n });
2003
- this.pushInstruction({ op: "local.set", index: resNTmp });
2004
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2005
- this.pushInstruction({ op: "local.set", index: resErrTmp });
2006
- this.pushInstruction("else");
2007
-
2008
- const remLenTmp = this.acquireTemp("i32");
2009
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
2010
- this.pushInstruction({ op: "local.get", index: posTmp });
2011
- this.pushInstruction("i32.wrap_i64");
2012
- this.pushInstruction("i32.sub");
2013
- this.pushInstruction({ op: "local.set", index: remLenTmp });
2014
-
2015
- const subsliceTmp = this.acquireTemp(sliceW);
2016
- this.pushInstruction({ op: "local.get", index: srcArrTmp });
2017
- this.pushInstruction({ op: "local.get", index: srcOffTmp });
2018
- this.pushInstruction({ op: "local.get", index: posTmp });
2019
- this.pushInstruction("i32.wrap_i64");
2020
- this.pushInstruction("i32.add");
2021
- this.pushInstruction({ op: "local.get", index: remLenTmp });
2022
- this.pushInstruction({ op: "local.get", index: srcCapTmp });
2023
- this.pushInstruction({ op: "local.get", index: posTmp });
2024
- this.pushInstruction("i32.wrap_i64");
2025
- this.pushInstruction("i32.sub");
2026
- this.pushInstruction({
2027
- op: "struct.new",
2028
- typeIndex: sliceInfo.typeIndex,
2029
- });
2030
- this.pushInstruction({ op: "local.set", index: subsliceTmp });
2031
-
2032
- const dispatchWriteIdx = this.mod.resolveFuncIndex(
2033
- "__dispatch_io.Writer_Write",
2034
- );
2035
- this.pushInstruction({ op: "local.get", index: wTmp });
2036
- this.pushInstruction({ op: "local.get", index: subsliceTmp });
2037
- if (dispatchWriteIdx !== null) {
2038
- this.pushInstruction({ op: "call", funcIndex: dispatchWriteIdx });
2039
- } else {
2040
- this.pushInstruction({ op: "i64.const", value: 0n });
2041
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2042
- }
2043
- this.pushInstruction({ op: "local.set", index: resErrTmp });
2044
- this.pushInstruction({ op: "local.set", index: resNTmp });
2045
-
2046
- this.pushInstruction({ op: "local.get", index: rTmp });
2047
- this.pushInstruction({ op: "local.get", index: posTmp });
2048
- this.pushInstruction({ op: "local.get", index: resNTmp });
2049
- this.pushInstruction("i64.add");
2050
- this.pushInstruction({
2051
- op: "struct.set",
2052
- typeIndex: structInfo.typeIndex,
2053
- fieldIndex: 1,
2054
- });
2055
-
2056
- if (structInfo.fields.length > 2) {
2057
- this.pushInstruction({ op: "local.get", index: rTmp });
2058
- this.pushInstruction({ op: "i64.const", value: -1n });
2059
- this.pushInstruction({
2060
- op: "struct.set",
2061
- typeIndex: structInfo.typeIndex,
2062
- fieldIndex: 2,
2063
- });
2064
- }
2065
-
2066
- this.releaseTemp(subsliceTmp, sliceW);
2067
- this.releaseTemp(remLenTmp, "i32");
2068
- this.pushInstruction("end");
2069
-
2070
- this.pushInstruction({ op: "local.get", index: resNTmp });
2071
- this.pushInstruction({ op: "local.get", index: resErrTmp });
2072
-
2073
- this.releaseTemp(resErrTmp, "anyref");
2074
- this.releaseTemp(resNTmp, "i64");
2075
- this.releaseTemp(posTmp, "i64");
2076
- this.releaseTemp(srcCapTmp, "i32");
2077
- this.releaseTemp(srcLenTmp, "i32");
2078
- this.releaseTemp(srcOffTmp, "i32");
2079
- this.releaseTemp(srcArrTmp, arrW);
2080
- this.releaseTemp(wTmp, "anyref");
2081
- this.releaseTemp(rTmp, readerW);
2082
- }
2083
-
2084
- emitFprintCall(fn, call, _targetWasmType) {
2085
- const wExpr = call.args[0];
2086
- const strTmp = this.acquireTemp("externref");
2087
- this._emitFprintFormatString(fn, call.args.slice(1));
2088
- this.pushInstruction({ op: "local.set", index: strTmp });
2089
-
2090
- const wType = wExpr._type;
2091
- const targetName =
2092
- wType?.name ?? (wType?.kind === "pointer" ? wType.base?.name : null);
2093
- if (targetName === "strings.Builder") {
2094
- // Builder.WriteString
2095
- const builderInfo = this.mod.getStructType("strings.Builder");
2096
- const builderW = {
2097
- kind: "ref",
2098
- nullable: true,
2099
- typeIndex: builderInfo.typeIndex,
2100
- };
2101
- const bTmp = this.acquireTemp(builderW);
2102
- this.emitExpr(wExpr, builderW);
2103
- this.pushInstruction({ op: "local.set", index: bTmp });
2104
- this._emitBuilderWriteStringCore(bTmp, strTmp);
2105
- this.releaseTemp(bTmp, builderW);
2106
- this.pushInstruction({ op: "local.get", index: strTmp });
2107
- this.pushInstruction({
2108
- op: "call",
2109
- funcIndex: this.mod.getStringLenImportIndex(),
2110
- });
2111
- this.pushInstruction("i64.extend_i32_u");
2112
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2113
- this.releaseTemp(strTmp, "externref");
2114
- return;
2115
- }
2116
- if (targetName === "bytes.Buffer") {
2117
- const bufInfo = this.mod.getStructType("bytes.Buffer");
2118
- const bufW = {
2119
- kind: "ref",
2120
- nullable: true,
2121
- typeIndex: bufInfo.typeIndex,
2122
- };
2123
- const bTmp = this.acquireTemp(bufW);
2124
- this.emitExpr(wExpr, bufW);
2125
- this.pushInstruction({ op: "local.set", index: bTmp });
2126
- this._emitBufferWriteStringCore(bTmp, strTmp);
2127
- this.releaseTemp(bTmp, bufW);
2128
- this.pushInstruction({ op: "local.get", index: strTmp });
2129
- this.pushInstruction({
2130
- op: "call",
2131
- funcIndex: this.mod.getStringLenImportIndex(),
2132
- });
2133
- this.pushInstruction("i64.extend_i32_u");
2134
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2135
- this.releaseTemp(strTmp, "externref");
2136
- return;
2137
- }
2138
-
2139
- this._emitWriterWrite(wExpr, strTmp);
2140
- this.releaseTemp(strTmp, "externref");
2141
- }
2142
-
2143
- _emitFprintFormatString(fn, restArgs) {
2144
- if (fn === "Fprintf") {
2145
- const [format, ...rest] = restArgs;
2146
- const temps = this._emitArgBuffer(
2147
- rest,
2148
- false,
2149
- this._fmtNeedsTypes(format, rest),
2150
- );
2151
- this.emitExpr(format, "externref");
2152
- this._callStdlib("fmt_sprintf");
2153
- this._releaseArgBuffer(temps);
2154
- return;
2155
- }
2156
- const argc = restArgs.length;
2157
- if (argc === 0) {
2158
- const s = fn === "Fprintln" ? "\n" : "";
2159
- const strIdx = this.mod.internString(s);
2160
- this.pushInstruction({ op: "i32.const", value: strIdx });
2161
- this.pushInstruction({
2162
- op: "call",
2163
- funcIndex: this.mod.getStringImportIndex(),
2164
- });
2165
- return;
2166
- }
2167
- const sep = fn === "Fprintln" ? " " : "";
2168
- const suffix = fn === "Fprintln" ? "\n" : "";
2169
- const fmt = Array(argc).fill("%v").join(sep) + suffix;
2170
- const temps = this._emitArgBuffer(restArgs);
2171
- const strIdx = this.mod.internString(fmt);
2172
- this.pushInstruction({ op: "i32.const", value: strIdx });
2173
- this.pushInstruction({
2174
- op: "call",
2175
- funcIndex: this.mod.getStringImportIndex(),
2176
- });
2177
- this._callStdlib("fmt_sprintf");
2178
- this._releaseArgBuffer(temps);
2179
- }
2180
-
2181
- emitSscanCall(fn, call, _targetWasmType) {
2182
- const strArg = call.args[0];
2183
- const mode = fn === "Sscanln" ? 1 : 0;
2184
- const ptrs = fn === "Sscanf" ? call.args.slice(2) : call.args.slice(1);
2185
-
2186
- if (fn === "Sscanf") {
2187
- this.emitExpr(strArg, "externref");
2188
- this.emitExpr(call.args[1], "externref");
2189
- this._callStdlib("fmt_sscanf_init");
2190
- } else {
2191
- this.emitExpr(strArg, "externref");
2192
- this.pushInstruction({ op: "i32.const", value: mode });
2193
- this._callStdlib("fmt_sscan_init");
2194
- }
2195
- const totTokensTmp = this.acquireTemp("i32");
2196
- this.pushInstruction({ op: "local.set", index: totTokensTmp });
2197
-
2198
- const nTmp = this.acquireTemp("i64");
2199
- this.pushInstruction({ op: "i64.const", value: 0n });
2200
- this.pushInstruction({ op: "local.set", index: nTmp });
2201
-
2202
- const isSpread = ptrs.length === 1 && (ptrs[0]._spread || ptrs[0].ellipsis);
2203
- const sliceLenTmp = isSpread ? this.acquireTemp("i32") : null;
2204
-
2205
- if (isSpread) {
2206
- this._emitSscanAssignSpread(ptrs[0], totTokensTmp, nTmp, sliceLenTmp);
2207
- } else {
2208
- for (let i = 0; i < ptrs.length; i++) {
2209
- this._emitSscanAssignOne(ptrs[i], i, totTokensTmp, nTmp);
2210
- }
2211
- }
2212
-
2213
- // return (n: i64, err: anyref)
2214
- this.pushInstruction({ op: "local.get", index: nTmp });
2215
-
2216
- this._callStdlib("fmt_sscan_has_err");
2217
- this.pushInstruction({ op: "if", blockType: "anyref" });
2218
- this._callStdlib("fmt_sscan_err_msg");
2219
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2220
- this.pushInstruction({
2221
- op: "call",
2222
- funcIndex: this.mod.resolveFuncIndex("__mk_error"),
2223
- });
2224
- this.pushInstruction("else");
2225
- this.pushInstruction({ op: "local.get", index: nTmp });
2226
- if (isSpread) {
2227
- this.pushInstruction({ op: "local.get", index: sliceLenTmp });
2228
- this.pushInstruction("i64.extend_i32_u");
2229
- } else {
2230
- this.pushInstruction({ op: "i64.const", value: BigInt(ptrs.length) });
2231
- }
2232
- this.pushInstruction("i64.lt_s");
2233
- this.pushInstruction({ op: "if", blockType: "anyref" });
2234
- const strIdx = this.mod.internString("unexpected EOF");
2235
- this.pushInstruction({ op: "i32.const", value: strIdx });
2236
- this.pushInstruction({
2237
- op: "call",
2238
- funcIndex: this.mod.getStringImportIndex(),
2239
- });
2240
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2241
- this.pushInstruction({
2242
- op: "call",
2243
- funcIndex: this.mod.resolveFuncIndex("__mk_error"),
2244
- });
2245
- this.pushInstruction("else");
2246
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2247
- this.pushInstruction("end");
2248
- this.pushInstruction("end");
2249
-
2250
- if (sliceLenTmp !== null) this.releaseTemp(sliceLenTmp, "i32");
2251
- this.releaseTemp(nTmp, "i64");
2252
- this.releaseTemp(totTokensTmp, "i32");
2253
- }
2254
-
2255
- _emitSscanAssignSpread(sliceNode, totTokensTmp, nTmp, sliceLenTmp) {
2256
- const sliceGoType = sliceNode._type ?? {
2257
- kind: "slice",
2258
- elem: { kind: "basic", name: "any" },
2259
- };
2260
- const sliceWType = this.toWasmType(sliceGoType);
2261
- const sliceInfo = this.mod.getSliceType(sliceGoType.elem);
2262
- const arrInfo = this.mod.getArrayType(sliceGoType.elem);
2263
- const sliceTmp = this.acquireTemp(sliceWType);
2264
- this.emitExpr(sliceNode, sliceWType);
2265
- this.pushInstruction({ op: "local.set", index: sliceTmp });
2266
-
2267
- // Read slice.len (field 2)
2268
- this.pushInstruction({ op: "local.get", index: sliceTmp });
2269
- this.pushInstruction({
2270
- op: "struct.get",
2271
- typeIndex: sliceInfo.typeIndex,
2272
- fieldIndex: 2,
2273
- });
2274
- this.pushInstruction({ op: "local.set", index: sliceLenTmp });
2275
-
2276
- // Loop index i = 0
2277
- const idxTmp = this.acquireTemp("i32");
2278
- this.pushInstruction({ op: "i32.const", value: 0 });
2279
- this.pushInstruction({ op: "local.set", index: idxTmp });
2280
-
2281
- // Loop: block $exit, loop $loop
2282
- this.pushInstruction({ op: "block", blockType: "void" });
2283
- this.pushInstruction({ op: "loop", blockType: "void" });
2284
-
2285
- // if i >= sliceLen, break $exit
2286
- this.pushInstruction({ op: "local.get", index: idxTmp });
2287
- this.pushInstruction({ op: "local.get", index: sliceLenTmp });
2288
- this.pushInstruction("i32.ge_s");
2289
- this.pushInstruction({ op: "br_if", depth: 1 });
2290
-
2291
- // if i >= totTokens, break $exit
2292
- this.pushInstruction({ op: "local.get", index: idxTmp });
2293
- this.pushInstruction({ op: "local.get", index: totTokensTmp });
2294
- this.pushInstruction("i32.ge_s");
2295
- this.pushInstruction({ op: "br_if", depth: 1 });
2296
-
2297
- // check fmt_sscan_has_err
2298
- this._callStdlib("fmt_sscan_has_err");
2299
- this.pushInstruction({ op: "br_if", depth: 1 });
2300
-
2301
- // Load ptr = slice.data[slice.offset + i]
2302
- this.pushInstruction({ op: "local.get", index: sliceTmp });
2303
- this.pushInstruction({
2304
- op: "struct.get",
2305
- typeIndex: sliceInfo.typeIndex,
2306
- fieldIndex: 0,
2307
- });
2308
- this.pushInstruction({ op: "local.get", index: sliceTmp });
2309
- this.pushInstruction({
2310
- op: "struct.get",
2311
- typeIndex: sliceInfo.typeIndex,
2312
- fieldIndex: 1,
2313
- });
2314
- this.pushInstruction({ op: "local.get", index: idxTmp });
2315
- this.pushInstruction("i32.add");
2316
- this.pushInstruction({
2317
- op: "array.get",
2318
- typeIndex: arrInfo.typeIndex,
2319
- });
2320
-
2321
- const elemTmp = this.acquireTemp("anyref");
2322
- this.pushInstruction({ op: "local.set", index: elemTmp });
2323
-
2324
- // Test and write to the box
2325
- this._emitSscanWriteAny(elemTmp, idxTmp, nTmp);
2326
-
2327
- this.releaseTemp(elemTmp, "anyref");
2328
-
2329
- // i++
2330
- this.pushInstruction({ op: "local.get", index: idxTmp });
2331
- this.pushInstruction({ op: "i32.const", value: 1 });
2332
- this.pushInstruction("i32.add");
2333
- this.pushInstruction({ op: "local.set", index: idxTmp });
2334
-
2335
- // loop again
2336
- this.pushInstruction({ op: "br", depth: 0 });
2337
- this.pushInstruction("end"); // loop
2338
- this.pushInstruction("end"); // block
2339
-
2340
- this.releaseTemp(idxTmp, "i32");
2341
- this.releaseTemp(sliceTmp, sliceWType);
2342
- }
2343
-
2344
- _emitSscanWriteAny(elemTmp, idxTmp, nTmp) {
2345
- const types = [
2346
- {
2347
- goType: { kind: "basic", name: "int" },
2348
- call: "fmt_sscan_token_i64",
2349
- wrap: null,
2350
- },
2351
- {
2352
- goType: { kind: "basic", name: "int64" },
2353
- call: "fmt_sscan_token_i64",
2354
- wrap: null,
2355
- },
2356
- {
2357
- goType: { kind: "basic", name: "uint" },
2358
- call: "fmt_sscan_token_i64",
2359
- wrap: null,
2360
- },
2361
- {
2362
- goType: { kind: "basic", name: "uint64" },
2363
- call: "fmt_sscan_token_i64",
2364
- wrap: null,
2365
- },
2366
- {
2367
- goType: { kind: "basic", name: "uintptr" },
2368
- call: "fmt_sscan_token_i64",
2369
- wrap: null,
2370
- },
2371
- {
2372
- goType: { kind: "basic", name: "int32" },
2373
- call: "fmt_sscan_token_i64",
2374
- wrap: "i32.wrap_i64",
2375
- },
2376
- {
2377
- goType: { kind: "basic", name: "uint32" },
2378
- call: "fmt_sscan_token_i64",
2379
- wrap: "i32.wrap_i64",
2380
- },
2381
- {
2382
- goType: { kind: "basic", name: "int16" },
2383
- call: "fmt_sscan_token_i64",
2384
- wrap: "i32.wrap_i64",
2385
- },
2386
- {
2387
- goType: { kind: "basic", name: "uint16" },
2388
- call: "fmt_sscan_token_i64",
2389
- wrap: "i32.wrap_i64",
2390
- },
2391
- {
2392
- goType: { kind: "basic", name: "int8" },
2393
- call: "fmt_sscan_token_i64",
2394
- wrap: "i32.wrap_i64",
2395
- },
2396
- {
2397
- goType: { kind: "basic", name: "uint8" },
2398
- call: "fmt_sscan_token_i64",
2399
- wrap: "i32.wrap_i64",
2400
- },
2401
- {
2402
- goType: { kind: "basic", name: "float64" },
2403
- call: "fmt_sscan_token_f64",
2404
- wrap: null,
2405
- },
2406
- {
2407
- goType: { kind: "basic", name: "float32" },
2408
- call: "fmt_sscan_token_f64",
2409
- wrap: "f32.demote_f64",
2410
- },
2411
- {
2412
- goType: { kind: "basic", name: "string" },
2413
- call: "fmt_sscan_token_str",
2414
- wrap: null,
2415
- },
2416
- {
2417
- goType: { kind: "basic", name: "bool" },
2418
- call: "fmt_sscan_token_bool",
2419
- wrap: null,
2420
- },
2421
- ];
2422
-
2423
- let ends = 0;
2424
- for (const { goType, call, wrap } of types) {
2425
- const ptrGoType = { kind: "pointer", base: goType };
2426
- const ifaceBox = this.mod.getIfaceBoxType(ptrGoType);
2427
- const scalarBox = this.mod.getBoxType(goType);
2428
-
2429
- // Arm 1: wrapped in ifaceBox
2430
- this.pushInstruction({ op: "local.get", index: elemTmp });
2431
- this.pushInstruction({ op: "ref.test", typeIndex: ifaceBox.typeIndex });
2432
- this.pushInstruction({ op: "if", blockType: "void" });
2433
- this.pushInstruction({ op: "local.get", index: elemTmp });
2434
- this.pushInstruction({ op: "ref.cast", typeIndex: ifaceBox.typeIndex });
2435
- this.pushInstruction({
2436
- op: "struct.get",
2437
- typeIndex: ifaceBox.typeIndex,
2438
- fieldIndex: 0,
2439
- });
2440
- this.pushInstruction({ op: "ref.cast", typeIndex: scalarBox.typeIndex });
2441
- this.pushInstruction({ op: "local.get", index: idxTmp });
2442
- this._callStdlib(call);
2443
- if (wrap) this.pushInstruction(wrap);
2444
- this.pushInstruction({
2445
- op: "struct.set",
2446
- typeIndex: scalarBox.typeIndex,
2447
- fieldIndex: 0,
2448
- });
2449
- this._emitIncrementN(nTmp);
2450
- this.pushInstruction("else");
2451
- ends++;
2452
-
2453
- // Arm 2: bare scalarBox
2454
- this.pushInstruction({ op: "local.get", index: elemTmp });
2455
- this.pushInstruction({ op: "ref.test", typeIndex: scalarBox.typeIndex });
2456
- this.pushInstruction({ op: "if", blockType: "void" });
2457
- this.pushInstruction({ op: "local.get", index: elemTmp });
2458
- this.pushInstruction({ op: "ref.cast", typeIndex: scalarBox.typeIndex });
2459
- this.pushInstruction({ op: "local.get", index: idxTmp });
2460
- this._callStdlib(call);
2461
- if (wrap) this.pushInstruction(wrap);
2462
- this.pushInstruction({
2463
- op: "struct.set",
2464
- typeIndex: scalarBox.typeIndex,
2465
- fieldIndex: 0,
2466
- });
2467
- this._emitIncrementN(nTmp);
2468
- this.pushInstruction("else");
2469
- ends++;
2470
- }
2471
-
2472
- for (let i = 0; i < ends; i++) {
2473
- this.pushInstruction("end");
2474
- }
2475
- }
2476
-
2477
- _emitIncrementN(nTmp) {
2478
- this._callStdlib("fmt_sscan_has_err");
2479
- this.pushInstruction({ op: "if", blockType: "void" });
2480
- this.pushInstruction("else");
2481
- this.pushInstruction({ op: "local.get", index: nTmp });
2482
- this.pushInstruction({ op: "i64.const", value: 1n });
2483
- this.pushInstruction("i64.add");
2484
- this.pushInstruction({ op: "local.set", index: nTmp });
2485
- this.pushInstruction("end");
2486
- }
2487
-
2488
- _emitSscanAssignOne(pExpr, tokenIdx, totTokensTmp, nTmp) {
2489
- this.pushInstruction({ op: "i32.const", value: tokenIdx });
2490
- this.pushInstruction({ op: "local.get", index: totTokensTmp });
2491
- this.pushInstruction("i32.lt_s");
2492
- this.pushInstruction({ op: "if", blockType: "void" });
2493
-
2494
- this._callStdlib("fmt_sscan_has_err");
2495
- this.pushInstruction({ op: "if", blockType: "void" });
2496
- this.pushInstruction("else");
2497
-
2498
- this._emitSscanWriteToken(pExpr, tokenIdx);
2499
-
2500
- this._callStdlib("fmt_sscan_has_err");
2501
- this.pushInstruction({ op: "if", blockType: "void" });
2502
- this.pushInstruction("else");
2503
- this.pushInstruction({ op: "local.get", index: nTmp });
2504
- this.pushInstruction({ op: "i64.const", value: 1n });
2505
- this.pushInstruction("i64.add");
2506
- this.pushInstruction({ op: "local.set", index: nTmp });
2507
- this.pushInstruction("end");
2508
-
2509
- this.pushInstruction("end");
2510
- this.pushInstruction("end");
2511
- }
2512
-
2513
- _emitSscanWriteToken(pExpr, tokenIdx) {
2514
- const isAddressOf = pExpr.kind === "UnaryExpr" && pExpr.op === "&";
2515
- const pType =
2516
- pExpr._type ??
2517
- (pExpr.kind === "Ident" ? this.resolveLocal(pExpr.name)?.goType : null) ??
2518
- this._resolveExprGoType(pExpr);
2519
- const pointeeType = pType?.base ?? pType;
2520
- const targetNode = isAddressOf
2521
- ? (pExpr.operand ?? pExpr.expr)
2522
- : {
2523
- kind: "UnaryExpr",
2524
- op: "*",
2525
- operand: { ...pExpr, _type: pType },
2526
- _type: pointeeType,
2527
- };
2528
- const effectivePointee = targetNode._type ?? pointeeType;
2529
- const wType = toWasmType(effectivePointee, this.mod.checker, this.mod);
2530
-
2531
- this._emitAssignToTarget(targetNode, wType, effectivePointee, () => {
2532
- this._emitSscanTokenValue(wType, effectivePointee, tokenIdx);
2533
- });
2534
- }
2535
-
2536
- _emitSscanTokenValue(wType, pointeeType, tokenIdx) {
2537
- this.pushInstruction({ op: "i32.const", value: tokenIdx });
2538
- if (wType === "i64") {
2539
- this._callStdlib("fmt_sscan_token_i64");
2540
- return;
2541
- }
2542
- if (wType === "i32") {
2543
- if (pointeeType?.name === "bool") {
2544
- this._callStdlib("fmt_sscan_token_bool");
2545
- } else {
2546
- this._callStdlib("fmt_sscan_token_i64");
2547
- this.pushInstruction("i32.wrap_i64");
2548
- }
2549
- return;
2550
- }
2551
- if (wType === "f64") {
2552
- this._callStdlib("fmt_sscan_token_f64");
2553
- return;
2554
- }
2555
- if (wType === "f32") {
2556
- this._callStdlib("fmt_sscan_token_f64");
2557
- this.pushInstruction("f32.demote_f64");
2558
- return;
2559
- }
2560
- if (wType === "externref") {
2561
- this._callStdlib("fmt_sscan_token_str");
2562
- return;
2563
- }
2564
- this._callStdlib("fmt_sscan_token_str");
2565
- }
2566
-
2567
- emitIoHelper(fn) {
2568
- const kind = fn._isIoHelper ?? fn._isPhase7Helper;
2569
- switch (kind) {
2570
- case "builder_write":
2571
- this._emitHelperBuilderWrite(fn);
2572
- return;
2573
- case "builder_write_string":
2574
- this._emitHelperBuilderWriteString(fn);
2575
- return;
2576
- case "buffer_write":
2577
- this._emitHelperBufferWrite(fn);
2578
- return;
2579
- case "buffer_write_string":
2580
- this._emitHelperBufferWriteString(fn);
2581
- return;
2582
- case "buffer_read":
2583
- this._emitHelperBufferRead(fn);
2584
- return;
2585
- case "strings_reader_read":
2586
- this._emitHelperStringsReaderRead(fn);
2587
- return;
2588
- case "strings_reader_len":
2589
- this._emitHelperStringsReaderLen(fn);
2590
- return;
2591
- case "strings_reader_reset":
2592
- this._emitHelperStringsReaderReset(fn);
2593
- return;
2594
- case "bytes_reader_read":
2595
- this._emitHelperBytesReaderRead(fn);
2596
- return;
2597
- case "bytes_reader_len":
2598
- this._emitHelperBytesReaderLen(fn);
2599
- return;
2600
- case "bytes_reader_reset":
2601
- this._emitHelperBytesReaderReset(fn);
2602
- return;
2603
- case "discard_write":
2604
- this._emitHelperDiscardWrite(fn);
2605
- return;
2606
- case "discard_write_string":
2607
- this._emitHelperDiscardWriteString(fn);
2608
- return;
2609
- case "limited_reader_read":
2610
- this._emitHelperLimitedReaderRead(fn);
2611
- return;
2612
- case "sha256_write":
2613
- this._emitHelperSha256Write(fn);
2614
- return;
2615
- case "sha256_sum":
2616
- this._emitHelperSha256Sum(fn);
2617
- return;
2618
- case "sha256_reset":
2619
- this._emitHelperSha256Reset(fn);
2620
- return;
2621
- case "sha256_size":
2622
- this._emitHelperSha256Size(fn);
2623
- return;
2624
- case "sha256_block_size":
2625
- this._emitHelperSha256BlockSize(fn);
2626
- return;
2627
- case "os_file_write":
2628
- this._emitHelperOsFileWrite(fn);
2629
- return;
2630
- case "os_file_write_string":
2631
- this._emitHelperOsFileWriteString(fn);
2632
- return;
2633
- case "os_file_read":
2634
- this._emitHelperOsFileRead(fn);
2635
- return;
2636
- case "os_file_close":
2637
- this._emitHelperOsFileClose(fn);
2638
- return;
2639
- default:
2640
- throw new Error(`Unknown io helper: ${kind}`);
2641
- }
2642
- }
2643
-
2644
- emitPhase7Helper(fn) {
2645
- return this.emitIoHelper(fn);
2646
- }
2647
-
2648
- _emitHelperBuilderWrite(_fn) {
2649
- this._emitBuilderWriteCore(0, 1);
2650
- this.pushInstruction("return");
2651
- }
2652
-
2653
- _emitHelperBuilderWriteString(_fn) {
2654
- this._emitBuilderWriteStringCore(0, 1);
2655
- this.pushInstruction("return");
2656
- }
2657
-
2658
- _emitBuilderWriteCore(bTmp, pTmp) {
2659
- const byteElemGo = { kind: "basic", name: "byte" };
2660
- const sliceInfo = this.mod.getSliceType(byteElemGo);
2661
- const arrW = {
2662
- kind: "ref",
2663
- nullable: true,
2664
- typeIndex: sliceInfo.arrInfo.typeIndex,
2665
- };
2666
-
2667
- const pArrTmp = this.acquireTemp(arrW);
2668
- const pOffTmp = this.acquireTemp("i32");
2669
- const pLenTmp = this.acquireTemp("i32");
2670
- const pCapTmp = this.acquireTemp("i32");
2671
- this._emitSliceUnpack(pTmp, sliceInfo, {
2672
- arr: pArrTmp,
2673
- off: pOffTmp,
2674
- len: pLenTmp,
2675
- cap: pCapTmp,
2676
- });
2677
- this.releaseTemp(pCapTmp, "i32");
2678
-
2679
- this.pushInstruction({ op: "local.get", index: pLenTmp });
2680
- this._callStdlib("bytes_to_str_init");
2681
-
2682
- const kTmp = this.acquireTemp("i32");
2683
- this.pushInstruction({ op: "i32.const", value: 0 });
2684
- this.pushInstruction({ op: "local.set", index: kTmp });
2685
-
2686
- this.pushInstruction({ op: "block", blockType: "void" });
2687
- this.pushInstruction({ op: "loop", blockType: "void" });
2688
- this.pushInstruction({ op: "local.get", index: kTmp });
2689
- this.pushInstruction({ op: "local.get", index: pLenTmp });
2690
- this.pushInstruction("i32.ge_s");
2691
- this.pushInstruction({ op: "br_if", depth: 1 });
2692
-
2693
- this.pushInstruction({ op: "local.get", index: pArrTmp });
2694
- this.pushInstruction({ op: "local.get", index: pOffTmp });
2695
- this.pushInstruction({ op: "local.get", index: kTmp });
2696
- this.pushInstruction("i32.add");
2697
- this.pushInstruction({
2698
- op: "array.get",
2699
- typeIndex: sliceInfo.arrInfo.typeIndex,
2700
- });
2701
- this._callStdlib("bytes_to_str_push");
2702
-
2703
- this.pushInstruction({ op: "local.get", index: kTmp });
2704
- this.pushInstruction({ op: "i32.const", value: 1 });
2705
- this.pushInstruction("i32.add");
2706
- this.pushInstruction({ op: "local.set", index: kTmp });
2707
- this.pushInstruction({ op: "br", depth: 0 });
2708
- this.pushInstruction("end");
2709
- this.pushInstruction("end");
2710
-
2711
- this._callStdlib("bytes_to_str_finish");
2712
- const strTmp = this.acquireTemp("externref");
2713
- this.pushInstruction({ op: "local.set", index: strTmp });
2714
-
2715
- this._emitBuilderWriteStringCore(bTmp, strTmp);
2716
- this.releaseTemp(strTmp, "externref");
2717
- this.releaseTemp(kTmp, "i32");
2718
- this.releaseTemp(pLenTmp, "i32");
2719
- this.releaseTemp(pOffTmp, "i32");
2720
- this.releaseTemp(pArrTmp, arrW);
2721
- }
2722
-
2723
- _emitBuilderWriteStringCore(bTmp, strTmp) {
2724
- const structInfo = this.mod.getStructType("strings.Builder");
2725
- const strGo = { kind: "basic", name: "string" };
2726
- const sliceInfo = this.mod.getSliceType(strGo);
2727
- const arrInfo = sliceInfo.arrInfo;
2728
- const sliceW = {
2729
- kind: "ref",
2730
- nullable: true,
2731
- typeIndex: sliceInfo.typeIndex,
2732
- };
2733
- const arrW = { kind: "ref", nullable: true, typeIndex: arrInfo.typeIndex };
2734
-
2735
- const lenTmp = this.acquireTemp("i32");
2736
- this.pushInstruction({ op: "local.get", index: strTmp });
2737
- this.pushInstruction({
2738
- op: "call",
2739
- funcIndex: this.mod.getStringLenImportIndex(),
2740
- });
2741
- this.pushInstruction({ op: "local.set", index: lenTmp });
2742
-
2743
- // copy check
2744
- this.pushInstruction({ op: "local.get", index: bTmp });
2745
- this.pushInstruction({
2746
- op: "struct.get",
2747
- typeIndex: structInfo.typeIndex,
2748
- fieldIndex: 2,
2749
- });
2750
- this.pushInstruction("ref.is_null");
2751
- this.pushInstruction({ op: "if", blockType: "void" });
2752
- this.pushInstruction({ op: "local.get", index: bTmp });
2753
- this.pushInstruction({ op: "local.get", index: bTmp });
2754
- this.pushInstruction({
2755
- op: "struct.set",
2756
- typeIndex: structInfo.typeIndex,
2757
- fieldIndex: 2,
2758
- });
2759
- this.pushInstruction("else");
2760
- this.pushInstruction({ op: "local.get", index: bTmp });
2761
- this.pushInstruction({
2762
- op: "struct.get",
2763
- typeIndex: structInfo.typeIndex,
2764
- fieldIndex: 2,
2765
- });
2766
- this.pushInstruction({ op: "ref.cast", heapType: "eq" });
2767
- this.pushInstruction({ op: "local.get", index: bTmp });
2768
- this.pushInstruction("ref.eq");
2769
- this.pushInstruction("i32.eqz");
2770
- this.pushInstruction({ op: "if", blockType: "void" });
2771
- this.emitPanic("strings: illegal use of non-zero Builder copied by value");
2772
- this.pushInstruction("end");
2773
- this.pushInstruction("end");
2774
-
2775
- // append string to b._buf
2776
- const oldSliceTmp = this.acquireTemp(sliceW);
2777
- this.pushInstruction({ op: "local.get", index: bTmp });
2778
- this.pushInstruction({
2779
- op: "struct.get",
2780
- typeIndex: structInfo.typeIndex,
2781
- fieldIndex: 0,
2782
- });
2783
- this.pushInstruction({ op: "local.set", index: oldSliceTmp });
2784
-
2785
- const oldArrTmp = this.acquireTemp(arrW);
2786
- const oldOffTmp = this.acquireTemp("i32");
2787
- const oldLenTmp = this.acquireTemp("i32");
2788
- const oldCapTmp = this.acquireTemp("i32");
2789
- this._emitSliceUnpack(oldSliceTmp, sliceInfo, {
2790
- arr: oldArrTmp,
2791
- off: oldOffTmp,
2792
- len: oldLenTmp,
2793
- cap: oldCapTmp,
2794
- });
2795
- this.releaseTemp(oldSliceTmp, sliceW);
2796
-
2797
- const newArrTmp = this.acquireTemp(arrW);
2798
- const newOffTmp = this.acquireTemp("i32");
2799
- const newCapTmp = this.acquireTemp("i32");
2800
- const newLenTmp = this.acquireTemp("i32");
2801
- this.pushInstruction({ op: "local.get", index: oldLenTmp });
2802
- this.pushInstruction({ op: "i32.const", value: 1 });
2803
- this.pushInstruction("i32.add");
2804
- this.pushInstruction({ op: "local.set", index: newLenTmp });
2805
-
2806
- this._emitGrowSlice({
2807
- arrInfo,
2808
- elemGoType: strGo,
2809
- oldArrTmp,
2810
- oldOffTmp,
2811
- oldLenTmp,
2812
- oldCapTmp,
2813
- newArrTmp,
2814
- newOffTmp,
2815
- newLenTmp,
2816
- newCapTmp,
2817
- });
2818
-
2819
- this.pushInstruction({ op: "local.get", index: newArrTmp });
2820
- this.pushInstruction({ op: "local.get", index: newOffTmp });
2821
- this.pushInstruction({ op: "local.get", index: oldLenTmp });
2822
- this.pushInstruction("i32.add");
2823
- this.pushInstruction({ op: "local.get", index: strTmp });
2824
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
2825
-
2826
- this.pushInstruction({ op: "local.get", index: bTmp });
2827
- this.pushInstruction({ op: "local.get", index: newArrTmp });
2828
- this.pushInstruction({ op: "local.get", index: newOffTmp });
2829
- this.pushInstruction({ op: "local.get", index: newLenTmp });
2830
- this.pushInstruction({ op: "local.get", index: newCapTmp });
2831
- this.pushInstruction({
2832
- op: "struct.new",
2833
- typeIndex: sliceInfo.typeIndex,
2834
- });
2835
- this.pushInstruction({
2836
- op: "struct.set",
2837
- typeIndex: structInfo.typeIndex,
2838
- fieldIndex: 0,
2839
- });
2840
-
2841
- this.pushInstruction({ op: "local.get", index: bTmp });
2842
- this.pushInstruction({ op: "local.get", index: bTmp });
2843
- this.pushInstruction({
2844
- op: "struct.get",
2845
- typeIndex: structInfo.typeIndex,
2846
- fieldIndex: 1,
2847
- });
2848
- this.pushInstruction({ op: "local.get", index: lenTmp });
2849
- this.pushInstruction("i64.extend_i32_u");
2850
- this.pushInstruction("i64.add");
2851
- this.pushInstruction({
2852
- op: "struct.set",
2853
- typeIndex: structInfo.typeIndex,
2854
- fieldIndex: 1,
2855
- });
2856
-
2857
- // return (len, nil)
2858
- this.pushInstruction({ op: "local.get", index: lenTmp });
2859
- this.pushInstruction("i64.extend_i32_u");
2860
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2861
-
2862
- this.releaseTemp(newLenTmp, "i32");
2863
- this.releaseTemp(newCapTmp, "i32");
2864
- this.releaseTemp(newOffTmp, "i32");
2865
- this.releaseTemp(newArrTmp, arrW);
2866
- this.releaseTemp(oldCapTmp, "i32");
2867
- this.releaseTemp(oldLenTmp, "i32");
2868
- this.releaseTemp(oldOffTmp, "i32");
2869
- this.releaseTemp(oldArrTmp, arrW);
2870
- this.releaseTemp(lenTmp, "i32");
2871
- }
2872
-
2873
- _emitHelperBufferWrite(_fn) {
2874
- this._emitBufferWriteCore(0, 1);
2875
- this.pushInstruction("return");
2876
- }
2877
-
2878
- _emitHelperBufferWriteString(_fn) {
2879
- this._emitBufferWriteStringCore(0, 1);
2880
- this.pushInstruction("return");
2881
- }
2882
-
2883
- _emitBufferWriteCore(bTmp, pTmp, structName = "bytes.Buffer") {
2884
- const structInfo = this.mod.getStructType(structName);
2885
- const byteGo = { kind: "basic", name: "byte" };
2886
- const sliceInfo = this.mod.getSliceType(byteGo);
2887
- const sliceW = {
2888
- kind: "ref",
2889
- nullable: true,
2890
- typeIndex: sliceInfo.typeIndex,
2891
- };
2892
- const arrW = {
2893
- kind: "ref",
2894
- nullable: true,
2895
- typeIndex: sliceInfo.arrInfo.typeIndex,
2896
- };
2897
-
2898
- const bufSliceTmp = this.acquireTemp(sliceW);
2899
- this.pushInstruction({ op: "local.get", index: bTmp });
2900
- this.pushInstruction({
2901
- op: "struct.get",
2902
- typeIndex: structInfo.typeIndex,
2903
- fieldIndex: 0,
2904
- });
2905
- this.pushInstruction({ op: "local.set", index: bufSliceTmp });
2906
- this.pushInstruction({ op: "local.get", index: bufSliceTmp });
2907
- this.pushInstruction("ref.is_null");
2908
- this.pushInstruction({ op: "if", blockType: "void" });
2909
- this.pushInstruction({
2910
- op: "global.get",
2911
- index: sliceInfo.emptyGlobalIndex,
2912
- });
2913
- this.pushInstruction({ op: "local.set", index: bufSliceTmp });
2914
- this.pushInstruction("end");
2915
-
2916
- const pArrTmp = this.acquireTemp(arrW);
2917
- const pOffTmp = this.acquireTemp("i32");
2918
- const pLenTmp = this.acquireTemp("i32");
2919
- const pCapTmp = this.acquireTemp("i32");
2920
- this._emitSliceUnpack(pTmp, sliceInfo, {
2921
- arr: pArrTmp,
2922
- off: pOffTmp,
2923
- len: pLenTmp,
2924
- cap: pCapTmp,
2925
- });
2926
- this.releaseTemp(pCapTmp, "i32");
2927
-
2928
- this._emitAppendSliceBytes(bufSliceTmp, pTmp, pLenTmp, sliceInfo, arrW);
2929
-
2930
- this.pushInstruction({ op: "local.get", index: bTmp });
2931
- this.pushInstruction({ op: "local.get", index: bufSliceTmp });
2932
- this.pushInstruction({
2933
- op: "struct.set",
2934
- typeIndex: structInfo.typeIndex,
2935
- fieldIndex: 0,
2936
- });
2937
- if (structInfo.fields.length > 1) {
2938
- this.pushInstruction({ op: "local.get", index: bTmp });
2939
- this.pushInstruction({ op: "i64.const", value: 0n });
2940
- this.pushInstruction({
2941
- op: "struct.set",
2942
- typeIndex: structInfo.typeIndex,
2943
- fieldIndex: 1,
2944
- });
2945
- }
2946
-
2947
- this.pushInstruction({ op: "local.get", index: pLenTmp });
2948
- this.pushInstruction("i64.extend_i32_u");
2949
- this.pushInstruction({ op: "ref.null", heapType: "any" });
2950
-
2951
- this.releaseTemp(bufSliceTmp, sliceW);
2952
- this.releaseTemp(pLenTmp, "i32");
2953
- this.releaseTemp(pOffTmp, "i32");
2954
- this.releaseTemp(pArrTmp, arrW);
2955
- }
2956
-
2957
- _emitBufferWriteStringCore(bTmp, strTmp) {
2958
- const sliceW = {
2959
- kind: "ref",
2960
- nullable: true,
2961
- typeIndex: this.mod.getSliceType({ kind: "basic", name: "byte" })
2962
- .typeIndex,
2963
- };
2964
- const pTmp = this.acquireTemp(sliceW);
2965
- this.pushInstruction({ op: "local.get", index: strTmp });
2966
- this._emitStringToByteSlice({ elem: { kind: "basic", name: "byte" } });
2967
- this.pushInstruction({ op: "local.set", index: pTmp });
2968
-
2969
- this._emitBufferWriteCore(bTmp, pTmp);
2970
- this.releaseTemp(pTmp, sliceW);
2971
- }
2972
-
2973
- _emitHelperBufferRead(_fn) {
2974
- this._emitBufferReadCore(0, 1);
2975
- this.pushInstruction("return");
2976
- }
2977
-
2978
- _emitBufferReadCore(bTmp, pTmp) {
2979
- const structInfo = this.mod.getStructType("bytes.Buffer");
2980
- const byteElemGo = { kind: "basic", name: "byte" };
2981
- const sliceInfo = this.mod.getSliceType(byteElemGo);
2982
- const arrW = {
2983
- kind: "ref",
2984
- nullable: true,
2985
- typeIndex: sliceInfo.arrInfo.typeIndex,
2986
- };
2987
- const sliceW = {
2988
- kind: "ref",
2989
- nullable: true,
2990
- typeIndex: sliceInfo.typeIndex,
2991
- };
2992
-
2993
- const pArrTmp = this.acquireTemp(arrW);
2994
- const pOffTmp = this.acquireTemp("i32");
2995
- const pLenTmp = this.acquireTemp("i32");
2996
- const pCapTmp = this.acquireTemp("i32");
2997
- this._emitSliceUnpack(pTmp, sliceInfo, {
2998
- arr: pArrTmp,
2999
- off: pOffTmp,
3000
- len: pLenTmp,
3001
- cap: pCapTmp,
3002
- });
3003
- this.releaseTemp(pCapTmp, "i32");
3004
-
3005
- const resNTmp = this.acquireTemp("i64");
3006
- const resErrTmp = this.acquireTemp("anyref");
3007
-
3008
- // Get b.buf (field 0)
3009
- const bufSliceTmp = this.acquireTemp(sliceW);
3010
- this.pushInstruction({ op: "local.get", index: bTmp });
3011
- this.pushInstruction({
3012
- op: "struct.get",
3013
- typeIndex: structInfo.typeIndex,
3014
- fieldIndex: 0,
3015
- });
3016
- this.pushInstruction({ op: "local.set", index: bufSliceTmp });
3017
-
3018
- this.pushInstruction({ op: "local.get", index: bufSliceTmp });
3019
- this.pushInstruction("ref.is_null");
3020
- this.pushInstruction({ op: "if", blockType: "void" });
3021
- this.pushInstruction({
3022
- op: "global.get",
3023
- index: sliceInfo.emptyGlobalIndex,
3024
- });
3025
- this.pushInstruction({ op: "local.set", index: bufSliceTmp });
3026
- this.pushInstruction("end");
3027
-
3028
- const srcArrTmp = this.acquireTemp(arrW);
3029
- const srcOffTmp = this.acquireTemp("i32");
3030
- const srcLenTmp = this.acquireTemp("i32");
3031
- const srcCapTmp = this.acquireTemp("i32");
3032
- this._emitSliceUnpack(bufSliceTmp, sliceInfo, {
3033
- arr: srcArrTmp,
3034
- off: srcOffTmp,
3035
- len: srcLenTmp,
3036
- cap: srcCapTmp,
3037
- });
3038
- this.releaseTemp(bufSliceTmp, sliceW);
3039
-
3040
- // if srcLen == 0:
3041
- // if pLen == 0: (0, nil) else: (0, io.EOF)
3042
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
3043
- this.pushInstruction("i32.eqz");
3044
- this.pushInstruction({ op: "if", blockType: "void" });
3045
- this.pushInstruction({ op: "i64.const", value: 0n });
3046
- this.pushInstruction({ op: "local.set", index: resNTmp });
3047
- this.pushInstruction({ op: "local.get", index: pLenTmp });
3048
- this.pushInstruction("i32.eqz");
3049
- this.pushInstruction({ op: "if", blockType: "anyref" });
3050
- this.pushInstruction({ op: "ref.null", heapType: "any" });
3051
- this.pushInstruction("else");
3052
- this.emitIoConst("EOF", "anyref");
3053
- this.pushInstruction("end");
3054
- this.pushInstruction({ op: "local.set", index: resErrTmp });
3055
- if (structInfo.fields.length > 1) {
3056
- this.pushInstruction({ op: "local.get", index: bTmp });
3057
- this.pushInstruction({ op: "i64.const", value: 0n });
3058
- this.pushInstruction({
3059
- op: "struct.set",
3060
- typeIndex: structInfo.typeIndex,
3061
- fieldIndex: 1,
3062
- });
3063
- }
3064
- this.pushInstruction("else");
3065
-
3066
- // n = min(p.len, srcLen)
3067
- const nTmp = this.acquireTemp("i32");
3068
- this.pushInstruction({ op: "local.get", index: pLenTmp });
3069
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
3070
- this.pushInstruction("i32.lt_s");
3071
- this.pushInstruction({ op: "if", blockType: "i32" });
3072
- this.pushInstruction({ op: "local.get", index: pLenTmp });
3073
- this.pushInstruction("else");
3074
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
3075
- this.pushInstruction("end");
3076
- this.pushInstruction({ op: "local.set", index: nTmp });
3077
-
3078
- // copy: pArr[pOff .. pOff + n] = srcArr[srcOff .. srcOff + n]
3079
- this.pushInstruction({ op: "local.get", index: pArrTmp });
3080
- this.pushInstruction({ op: "local.get", index: pOffTmp });
3081
- this.pushInstruction({ op: "local.get", index: srcArrTmp });
3082
- this.pushInstruction({ op: "local.get", index: srcOffTmp });
3083
- this.pushInstruction({ op: "local.get", index: nTmp });
3084
- this._emitArrayCopy(sliceInfo.arrInfo, byteElemGo);
3085
-
3086
- // update b.buf: struct.new sliceInfo (srcArr, srcOff + n, srcLen - n, srcCap - n)
3087
- this.pushInstruction({ op: "local.get", index: bTmp });
3088
- this.pushInstruction({ op: "local.get", index: srcArrTmp });
3089
- this.pushInstruction({ op: "local.get", index: srcOffTmp });
3090
- this.pushInstruction({ op: "local.get", index: nTmp });
3091
- this.pushInstruction("i32.add");
3092
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
3093
- this.pushInstruction({ op: "local.get", index: nTmp });
3094
- this.pushInstruction("i32.sub");
3095
- this.pushInstruction({ op: "local.get", index: srcCapTmp });
3096
- this.pushInstruction({ op: "local.get", index: nTmp });
3097
- this.pushInstruction("i32.sub");
3098
- this.pushInstruction({
3099
- op: "struct.new",
3100
- typeIndex: sliceInfo.typeIndex,
3101
- });
3102
- this.pushInstruction({
3103
- op: "struct.set",
3104
- typeIndex: structInfo.typeIndex,
3105
- fieldIndex: 0,
3106
- });
3107
- if (structInfo.fields.length > 1) {
3108
- this.pushInstruction({ op: "local.get", index: bTmp });
3109
- this.pushInstruction({ op: "i64.const", value: 1n });
3110
- this.pushInstruction({
3111
- op: "struct.set",
3112
- typeIndex: structInfo.typeIndex,
3113
- fieldIndex: 1,
3114
- });
3115
- }
3116
-
3117
- this.pushInstruction({ op: "local.get", index: nTmp });
3118
- this.pushInstruction("i64.extend_i32_u");
3119
- this.pushInstruction({ op: "local.set", index: resNTmp });
3120
- this.pushInstruction({ op: "ref.null", heapType: "any" });
3121
- this.pushInstruction({ op: "local.set", index: resErrTmp });
3122
-
3123
- this.releaseTemp(nTmp, "i32");
3124
- this.pushInstruction("end"); // end else
3125
-
3126
- this.releaseTemp(srcCapTmp, "i32");
3127
- this.releaseTemp(srcLenTmp, "i32");
3128
- this.releaseTemp(srcOffTmp, "i32");
3129
- this.releaseTemp(srcArrTmp, arrW);
3130
-
3131
- this.pushInstruction({ op: "local.get", index: resNTmp });
3132
- this.pushInstruction({ op: "local.get", index: resErrTmp });
3133
-
3134
- this.releaseTemp(resErrTmp, "anyref");
3135
- this.releaseTemp(resNTmp, "i64");
3136
- this.releaseTemp(pLenTmp, "i32");
3137
- this.releaseTemp(pOffTmp, "i32");
3138
- this.releaseTemp(pArrTmp, arrW);
3139
- }
3140
-
3141
- _emitHelperStringsReaderRead(_fn) {
3142
- this._emitStringsReaderReadCore(0, 1);
3143
- this.pushInstruction("return");
3144
- }
3145
-
3146
- _emitHelperStringsReaderLen(_fn) {
3147
- this._emitStringsReaderLenCore(0, "i64");
3148
- this.pushInstruction("return");
3149
- }
3150
-
3151
- _emitHelperStringsReaderReset(_fn) {
3152
- this._emitStringsReaderResetCore(0, 1);
3153
- this.pushInstruction("return");
3154
- }
3155
-
3156
- _emitHelperBytesReaderRead(_fn) {
3157
- this._emitBytesReaderReadCore(0, 1);
3158
- this.pushInstruction("return");
3159
- }
3160
-
3161
- _emitHelperBytesReaderLen(_fn) {
3162
- this._emitBytesReaderLenCore(0, "i64");
3163
- this.pushInstruction("return");
3164
- }
3165
-
3166
- _emitHelperBytesReaderReset(_fn) {
3167
- this._emitBytesReaderResetCore(0, 1);
3168
- this.pushInstruction("return");
3169
- }
3170
-
3171
- _emitHelperDiscardWrite(_fn) {
3172
- const byteElemGo = { kind: "basic", name: "byte" };
3173
- const sliceInfo = this.mod.getSliceType(byteElemGo);
3174
- this.pushInstruction({ op: "local.get", index: 1 });
3175
- this.pushInstruction({
3176
- op: "struct.get",
3177
- typeIndex: sliceInfo.typeIndex,
3178
- fieldIndex: 2,
3179
- });
3180
- this.pushInstruction("i64.extend_i32_u");
3181
- this.pushInstruction({ op: "ref.null", heapType: "any" });
3182
- this.pushInstruction("return");
3183
- }
3184
-
3185
- _emitHelperDiscardWriteString(_fn) {
3186
- this.pushInstruction({ op: "local.get", index: 1 });
3187
- this.pushInstruction({
3188
- op: "call",
3189
- funcIndex: this.mod.getStringLenImportIndex(),
3190
- });
3191
- this.pushInstruction("i64.extend_i32_u");
3192
- this.pushInstruction({ op: "ref.null", heapType: "any" });
3193
- this.pushInstruction("return");
3194
- }
3195
-
3196
- _emitHelperOsFileWriteString(_fn) {
3197
- this.pushInstruction({ op: "local.get", index: 1 });
3198
- this._callStdlib("fmt_print_raw");
3199
- this.pushInstruction({ op: "local.get", index: 1 });
3200
- this.pushInstruction({
3201
- op: "call",
3202
- funcIndex: this.mod.getStringLenImportIndex(),
3203
- });
3204
- this.pushInstruction("i64.extend_i32_u");
3205
- this.pushInstruction({ op: "ref.null", heapType: "any" });
3206
- this.pushInstruction("return");
3207
- }
3208
-
3209
- _emitHelperOsFileWrite(_fn) {
3210
- this.pushInstruction({ op: "local.get", index: 1 });
3211
- this._emitByteSliceToString({ elem: { kind: "basic", name: "byte" } });
3212
- this._callStdlib("fmt_print_raw");
3213
- const byteElemGo = { kind: "basic", name: "byte" };
3214
- const sliceInfo = this.mod.getSliceType(byteElemGo);
3215
- this.pushInstruction({ op: "local.get", index: 1 });
3216
- this.pushInstruction({
3217
- op: "struct.get",
3218
- typeIndex: sliceInfo.typeIndex,
3219
- fieldIndex: 2,
3220
- });
3221
- this.pushInstruction("i64.extend_i32_u");
3222
- this.pushInstruction({ op: "ref.null", heapType: "any" });
3223
- this.pushInstruction("return");
3224
- }
3225
-
3226
- _emitHelperOsFileRead(_fn) {
3227
- this.pushInstruction({ op: "i64.const", value: 0n });
3228
- this._emitLazyErrorGlobal(this.mod.getIoErrGlobalIndex("EOF"), "EOF");
3229
- this.pushInstruction("return");
3230
- }
3231
-
3232
- _emitHelperOsFileClose(_fn) {
3233
- this.pushInstruction({ op: "ref.null", heapType: "any" });
3234
- this.pushInstruction("return");
3235
- }
3236
-
3237
- _emitHelperLimitedReaderRead(_fn) {
3238
- this._emitLimitedReaderReadCore(0, 1);
3239
- this.pushInstruction("return");
3240
- }
3241
-
3242
- _emitLimitedReaderReadCore(lTmp, pTmp) {
3243
- const structInfo = this.mod.getStructType("io.LimitedReader");
3244
- const byteElemGo = { kind: "basic", name: "byte" };
3245
- const sliceInfo = this.mod.getSliceType(byteElemGo);
3246
- const arrW = {
3247
- kind: "ref",
3248
- nullable: true,
3249
- typeIndex: sliceInfo.arrInfo.typeIndex,
3250
- };
3251
-
3252
- // 1. Check if l.N <= 0
3253
- this.pushInstruction({ op: "local.get", index: lTmp });
3254
- this.pushInstruction({
3255
- op: "struct.get",
3256
- typeIndex: structInfo.typeIndex,
3257
- fieldIndex: 1, // N
3258
- });
3259
- this.pushInstruction({ op: "i64.const", value: 0n });
3260
- this.pushInstruction("i64.le_s");
3261
- this.pushInstruction({ op: "if", blockType: "void" });
3262
- this.pushInstruction({ op: "i64.const", value: 0n });
3263
- this.emitIoConst("EOF", "anyref");
3264
- this.pushInstruction("return");
3265
- this.pushInstruction("end");
3266
-
3267
- // 2. If int64(len(p)) > l.N, subslice p = p[0:l.N]
3268
- const pArrTmp = this.acquireTemp(arrW);
3269
- const pOffTmp = this.acquireTemp("i32");
3270
- const pLenTmp = this.acquireTemp("i32");
3271
- const pCapTmp = this.acquireTemp("i32");
3272
- this._emitSliceUnpack(pTmp, sliceInfo, {
3273
- arr: pArrTmp,
3274
- off: pOffTmp,
3275
- len: pLenTmp,
3276
- cap: pCapTmp,
3277
- });
3278
-
3279
- this.pushInstruction({ op: "local.get", index: pLenTmp });
3280
- this.pushInstruction("i64.extend_i32_u");
3281
- this.pushInstruction({ op: "local.get", index: lTmp });
3282
- this.pushInstruction({
3283
- op: "struct.get",
3284
- typeIndex: structInfo.typeIndex,
3285
- fieldIndex: 1, // N
3286
- });
3287
- this.pushInstruction("i64.gt_s");
3288
- this.pushInstruction({ op: "if", blockType: "void" });
3289
- this.pushInstruction({ op: "local.get", index: lTmp });
3290
- this.pushInstruction({
3291
- op: "struct.get",
3292
- typeIndex: structInfo.typeIndex,
3293
- fieldIndex: 1,
3294
- });
3295
- this.pushInstruction("i32.wrap_i64");
3296
- this.pushInstruction({ op: "local.set", index: pLenTmp });
3297
- this.pushInstruction({ op: "local.get", index: pArrTmp });
3298
- this.pushInstruction({ op: "local.get", index: pOffTmp });
3299
- this.pushInstruction({ op: "local.get", index: pLenTmp });
3300
- this.pushInstruction({ op: "local.get", index: pCapTmp });
3301
- this.pushInstruction({
3302
- op: "struct.new",
3303
- typeIndex: sliceInfo.typeIndex,
3304
- });
3305
- this.pushInstruction({ op: "local.set", index: pTmp });
3306
- this.pushInstruction("end");
3307
-
3308
- this.releaseTemp(pCapTmp, "i32");
3309
- this.releaseTemp(pLenTmp, "i32");
3310
- this.releaseTemp(pOffTmp, "i32");
3311
- this.releaseTemp(pArrTmp, arrW);
3312
-
3313
- // 3. Call l.R.Read(p)
3314
- this.pushInstruction({ op: "local.get", index: lTmp });
3315
- this.pushInstruction({
3316
- op: "struct.get",
3317
- typeIndex: structInfo.typeIndex,
3318
- fieldIndex: 0, // R
3319
- });
3320
- this.pushInstruction({ op: "local.get", index: pTmp });
3321
-
3322
- const dispatchIdx = this.mod.resolveFuncIndex("__dispatch_io.Reader_Read");
3323
- if (dispatchIdx !== null) {
3324
- this.pushInstruction({ op: "call", funcIndex: dispatchIdx });
3325
- } else {
3326
- this.pushInstruction({ op: "i64.const", value: 0n });
3327
- this.pushInstruction({ op: "ref.null", heapType: "any" });
3328
- }
3329
-
3330
- const resErrTmp = this.acquireTemp("anyref");
3331
- const resNTmp = this.acquireTemp("i64");
3332
- this.pushInstruction({ op: "local.set", index: resErrTmp });
3333
- this.pushInstruction({ op: "local.set", index: resNTmp });
3334
-
3335
- // 4. Update l.N -= n:
3336
- this.pushInstruction({ op: "local.get", index: lTmp });
3337
- this.pushInstruction({ op: "local.get", index: lTmp });
3338
- this.pushInstruction({
3339
- op: "struct.get",
3340
- typeIndex: structInfo.typeIndex,
3341
- fieldIndex: 1, // N
3342
- });
3343
- this.pushInstruction({ op: "local.get", index: resNTmp });
3344
- this.pushInstruction("i64.sub");
3345
- this.pushInstruction({
3346
- op: "struct.set",
3347
- typeIndex: structInfo.typeIndex,
3348
- fieldIndex: 1, // N
3349
- });
3350
-
3351
- // 5. Return (n, err)
3352
- this.pushInstruction({ op: "local.get", index: resNTmp });
3353
- this.pushInstruction({ op: "local.get", index: resErrTmp });
3354
- this.releaseTemp(resNTmp, "i64");
3355
- this.releaseTemp(resErrTmp, "anyref");
3356
- }
3357
-
3358
- emitIoLimitedReaderMethodCall(method, recvExpr, args, _targetWasmType) {
3359
- if (method === "Read") {
3360
- const structInfo = this.mod.getStructType("io.LimitedReader");
3361
- const lrW = {
3362
- kind: "ref",
3363
- nullable: true,
3364
- typeIndex: structInfo.typeIndex,
3365
- };
3366
- const lTmp = this.acquireTemp(lrW);
3367
- this.emitExpr(recvExpr, lrW);
3368
- this.pushInstruction({ op: "local.set", index: lTmp });
3369
-
3370
- const byteElemGo = { kind: "basic", name: "byte" };
3371
- const sliceInfo = this.mod.getSliceType(byteElemGo);
3372
- const sliceW = {
3373
- kind: "ref",
3374
- nullable: true,
3375
- typeIndex: sliceInfo.typeIndex,
3376
- };
3377
- const pTmp = this.acquireTemp(sliceW);
3378
- this.emitExpr(args[0], sliceW);
3379
- this.pushInstruction({ op: "local.set", index: pTmp });
3380
-
3381
- this._emitLimitedReaderReadCore(lTmp, pTmp);
3382
- this.releaseTemp(pTmp, sliceW);
3383
- this.releaseTemp(lTmp, lrW);
3384
- return;
3385
- }
3386
- throw new Error(`Unsupported io.LimitedReader method: ${method}`);
3387
- }
3388
-
3389
- _emitHelperSha256Write(_fn) {
3390
- this._emitBufferWriteCore(0, 1, "sha256.digest");
3391
- this.pushInstruction("return");
3392
- }
3393
-
3394
- _emitHelperSha256Reset(_fn) {
3395
- const structInfo = this.mod.getStructType("sha256.digest");
3396
- const byteGo = { kind: "basic", name: "byte" };
3397
- const sliceInfo = this.mod.getSliceType(byteGo);
3398
- this.pushInstruction({ op: "local.get", index: 0 });
3399
- this.pushInstruction({
3400
- op: "global.get",
3401
- index: sliceInfo.emptyGlobalIndex,
3402
- });
3403
- this.pushInstruction({
3404
- op: "struct.set",
3405
- typeIndex: structInfo.typeIndex,
3406
- fieldIndex: 0,
3407
- });
3408
- this.pushInstruction("return");
3409
- }
3410
-
3411
- _emitHelperSha256Size(_fn) {
3412
- this.pushInstruction({ op: "i64.const", value: 32n });
3413
- this.pushInstruction("return");
3414
- }
3415
-
3416
- _emitHelperSha256BlockSize(_fn) {
3417
- this.pushInstruction({ op: "i64.const", value: 64n });
3418
- this.pushInstruction("return");
3419
- }
3420
-
3421
- _emitHelperSha256Sum(_fn) {
3422
- const structInfo = this.mod.getStructType("sha256.digest");
3423
- const byteGo = { kind: "basic", name: "byte" };
3424
- const sliceInfo = this.mod.getSliceType(byteGo);
3425
- const arrInfo = sliceInfo.arrInfo;
3426
- const sliceW = {
3427
- kind: "ref",
3428
- nullable: true,
3429
- typeIndex: sliceInfo.typeIndex,
3430
- };
3431
- const arrW = { kind: "ref", nullable: true, typeIndex: arrInfo.typeIndex };
3432
-
3433
- const bufSliceTmp = this.acquireTemp(sliceW);
3434
- this.pushInstruction({ op: "local.get", index: 0 });
3435
- this.pushInstruction({
3436
- op: "struct.get",
3437
- typeIndex: structInfo.typeIndex,
3438
- fieldIndex: 0,
3439
- });
3440
- this.pushInstruction({ op: "local.set", index: bufSliceTmp });
3441
-
3442
- this.pushInstruction({ op: "local.get", index: bufSliceTmp });
3443
- this.pushInstruction("ref.is_null");
3444
- this.pushInstruction({ op: "if", blockType: "void" });
3445
- this.pushInstruction({
3446
- op: "global.get",
3447
- index: sliceInfo.emptyGlobalIndex,
3448
- });
3449
- this.pushInstruction({ op: "local.set", index: bufSliceTmp });
3450
- this.pushInstruction("end");
3451
-
3452
- const dArrTmp = this.acquireTemp(arrW);
3453
- const dOffTmp = this.acquireTemp("i32");
3454
- const dLenTmp = this.acquireTemp("i32");
3455
- const dCapTmp = this.acquireTemp("i32");
3456
- this._emitSliceUnpack(bufSliceTmp, sliceInfo, {
3457
- arr: dArrTmp,
3458
- off: dOffTmp,
3459
- len: dLenTmp,
3460
- cap: dCapTmp,
3461
- });
3462
- this.releaseTemp(dCapTmp, "i32");
3463
-
3464
- this.pushInstruction({ op: "local.get", index: dLenTmp });
3465
- this._callStdlib("raw_bytes_init");
3466
-
3467
- const iLoc = this.acquireTemp("i32");
3468
- this.pushInstruction({ op: "i32.const", value: 0 });
3469
- this.pushInstruction({ op: "local.set", index: iLoc });
3470
-
3471
- this.pushInstruction({ op: "block", blockType: "void" });
3472
- this.pushInstruction({ op: "loop", blockType: "void" });
3473
- this.pushInstruction({ op: "local.get", index: iLoc });
3474
- this.pushInstruction({ op: "local.get", index: dLenTmp });
3475
- this.pushInstruction("i32.ge_s");
3476
- this.pushInstruction({ op: "br_if", depth: 1 });
3477
-
3478
- this.pushInstruction({ op: "local.get", index: dArrTmp });
3479
- this.pushInstruction({ op: "local.get", index: dOffTmp });
3480
- this.pushInstruction({ op: "local.get", index: iLoc });
3481
- this.pushInstruction("i32.add");
3482
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
3483
- this._callStdlib("raw_bytes_push");
3484
-
3485
- this.pushInstruction({ op: "local.get", index: iLoc });
3486
- this.pushInstruction({ op: "i32.const", value: 1 });
3487
- this.pushInstruction("i32.add");
3488
- this.pushInstruction({ op: "local.set", index: iLoc });
3489
- this.pushInstruction({ op: "br", depth: 0 });
3490
- this.pushInstruction("end");
3491
- this.pushInstruction("end");
3492
-
3493
- this._callStdlib("crypto_sha256_sum");
3494
- this.pushInstruction("drop");
3495
-
3496
- const outArrTmp = this.acquireTemp(arrW);
3497
- this.pushInstruction({ op: "i32.const", value: 32 });
3498
- this.pushInstruction({
3499
- op: "array.new_default",
3500
- typeIndex: arrInfo.typeIndex,
3501
- });
3502
- this.pushInstruction({ op: "local.set", index: outArrTmp });
3503
-
3504
- this.pushInstruction({ op: "i32.const", value: 0 });
3505
- this.pushInstruction({ op: "local.set", index: iLoc });
3506
-
3507
- this.pushInstruction({ op: "block", blockType: "void" });
3508
- this.pushInstruction({ op: "loop", blockType: "void" });
3509
- this.pushInstruction({ op: "local.get", index: iLoc });
3510
- this.pushInstruction({ op: "i32.const", value: 32 });
3511
- this.pushInstruction("i32.ge_s");
3512
- this.pushInstruction({ op: "br_if", depth: 1 });
3513
-
3514
- this.pushInstruction({ op: "local.get", index: outArrTmp });
3515
- this.pushInstruction({ op: "local.get", index: iLoc });
3516
- this.pushInstruction({ op: "local.get", index: iLoc });
3517
- this._callStdlib("raw_bytes_get");
3518
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
3519
-
3520
- this.pushInstruction({ op: "local.get", index: iLoc });
3521
- this.pushInstruction({ op: "i32.const", value: 1 });
3522
- this.pushInstruction("i32.add");
3523
- this.pushInstruction({ op: "local.set", index: iLoc });
3524
- this.pushInstruction({ op: "br", depth: 0 });
3525
- this.pushInstruction("end");
3526
- this.pushInstruction("end");
3527
-
3528
- const outSliceTmp = this.acquireTemp(sliceW);
3529
- this.pushInstruction({ op: "local.get", index: outArrTmp });
3530
- this.pushInstruction({ op: "i32.const", value: 0 });
3531
- this.pushInstruction({ op: "i32.const", value: 32 });
3532
- this.pushInstruction({ op: "i32.const", value: 32 });
3533
- this.pushInstruction({
3534
- op: "struct.new",
3535
- typeIndex: sliceInfo.typeIndex,
3536
- });
3537
- this.pushInstruction({ op: "local.set", index: outSliceTmp });
3538
-
3539
- this.pushInstruction({ op: "local.get", index: 1 });
3540
- this.pushInstruction("ref.is_null");
3541
- this.pushInstruction({ op: "if", blockType: "void" });
3542
- this.pushInstruction({ op: "local.get", index: outSliceTmp });
3543
- this.pushInstruction("return");
3544
- this.pushInstruction("end");
3545
-
3546
- this.pushInstruction({ op: "local.get", index: 1 });
3547
- this.pushInstruction({
3548
- op: "struct.get",
3549
- typeIndex: sliceInfo.typeIndex,
3550
- fieldIndex: 1,
3551
- });
3552
- this.pushInstruction("i32.eqz");
3553
- this.pushInstruction({ op: "if", blockType: "void" });
3554
- this.pushInstruction({ op: "local.get", index: outSliceTmp });
3555
- this.pushInstruction("return");
3556
- this.pushInstruction("end");
3557
-
3558
- const countTmp = this.acquireTemp("i32");
3559
- this.pushInstruction({ op: "i32.const", value: 32 });
3560
- this.pushInstruction({ op: "local.set", index: countTmp });
3561
- const bTmp = this.acquireTemp(sliceW);
3562
- this.pushInstruction({ op: "local.get", index: 1 });
3563
- this.pushInstruction({ op: "local.set", index: bTmp });
3564
- this._emitAppendSliceBytes(bTmp, outSliceTmp, countTmp, sliceInfo, arrW);
3565
- this.pushInstruction({ op: "local.get", index: bTmp });
3566
- this.pushInstruction("return");
3567
-
3568
- this.releaseTemp(bTmp, sliceW);
3569
- this.releaseTemp(countTmp, "i32");
3570
- this.releaseTemp(outSliceTmp, sliceW);
3571
- this.releaseTemp(outArrTmp, arrW);
3572
- this.releaseTemp(iLoc, "i32");
3573
- this.releaseTemp(dLenTmp, "i32");
3574
- this.releaseTemp(dOffTmp, "i32");
3575
- this.releaseTemp(dArrTmp, arrW);
3576
- this.releaseTemp(bufSliceTmp, sliceW);
3577
- }
3578
- }