gofront 1.7.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 (194) hide show
  1. package/README.md +14 -14
  2. package/package.json +10 -38
  3. package/src/backend/js/expressions.js +2060 -389
  4. package/src/backend/js/index.js +586 -174
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +936 -1644
  7. package/src/backend/js/statements.js +1349 -132
  8. package/src/backend/js/stdlib/index.js +51 -94
  9. package/src/backend/js/templ.js +67 -118
  10. package/src/backend/js/type-info.js +436 -0
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +80 -0
  13. package/src/backend/shared/host-unicode.js +36 -0
  14. package/src/backend/wasm/boundary.js +753 -872
  15. package/src/backend/wasm/emit-builtins.js +914 -237
  16. package/src/backend/wasm/emit-exprs.js +1456 -195
  17. package/src/backend/wasm/emit-maps.js +78 -380
  18. package/src/backend/wasm/emit-stmts.js +1659 -214
  19. package/src/backend/wasm/emit.js +614 -88
  20. package/src/backend/wasm/encode.js +43 -13
  21. package/src/backend/wasm/globals.js +491 -0
  22. package/src/backend/wasm/glue.js +2 -4
  23. package/src/backend/wasm/index.js +406 -3195
  24. package/src/backend/wasm/method-expr.js +392 -0
  25. package/src/backend/wasm/module-emitter.js +1615 -0
  26. package/src/backend/wasm/monomorph.js +164 -9
  27. package/src/backend/wasm/natives.js +596 -0
  28. package/src/backend/wasm/prescan.js +249 -0
  29. package/src/backend/wasm/prune-funcs.js +89 -0
  30. package/src/backend/wasm/stdlib/index.js +2 -37
  31. package/src/backend/wasm/stdlib/simd.js +293 -28
  32. package/src/backend/wasm/types.js +260 -27
  33. package/src/backend/wasm/variadic.js +93 -0
  34. package/src/backend/wasm/wat.js +47 -20
  35. package/src/{cli-core.js → cli/cli-core.js} +241 -11
  36. package/src/{test-runner.js → cli/test-runner.js} +188 -122
  37. package/src/{vendor.js → cli/vendor.js} +3 -4
  38. package/src/compiler.js +202 -386
  39. package/src/index.js +15 -169
  40. package/src/{lexer.js → lexer/lexer.js} +203 -62
  41. package/src/{templ-lexer.js → lexer/templ-lexer.js} +61 -18
  42. package/src/{tokens.js → lexer/tokens.js} +2 -0
  43. package/src/link/sourcemap.js +97 -0
  44. package/src/link/stdlib.js +737 -0
  45. package/src/link/type-names.js +148 -0
  46. package/src/link/wasm.js +318 -0
  47. package/src/lower/bounds.js +547 -0
  48. package/src/lower/boxing.js +1 -1
  49. package/src/lower/captures.js +267 -64
  50. package/src/lower/embedding.js +32 -3
  51. package/src/lower/errors-as.js +196 -0
  52. package/src/lower/fmt-formatters.js +905 -0
  53. package/src/lower/functions.js +2 -0
  54. package/src/lower/gen-types.js +274 -0
  55. package/src/lower/index.js +33 -19
  56. package/src/lower/json-codecs.js +1379 -0
  57. package/src/lower/ownership.js +47 -8
  58. package/src/lower/range.js +86 -1
  59. package/src/lower/reachability.js +150 -0
  60. package/src/lower/walk.js +12 -0
  61. package/src/parser/declarations.js +83 -15
  62. package/src/parser/expressions.js +110 -18
  63. package/src/parser/index.js +2 -1
  64. package/src/parser/statements.js +38 -22
  65. package/src/{templ-parser.js → parser/templ.js} +179 -17
  66. package/src/parser/types.js +70 -9
  67. package/src/resolver.js +21 -1
  68. package/src/typechecker/assignability.js +291 -19
  69. package/src/typechecker/const-fold.js +399 -0
  70. package/src/typechecker/constants.js +282 -0
  71. package/src/typechecker/expressions.js +1220 -183
  72. package/src/typechecker/index.js +659 -92
  73. package/src/typechecker/init-order.js +426 -0
  74. package/src/typechecker/operand-text.js +40 -0
  75. package/src/typechecker/resolve.js +613 -62
  76. package/src/typechecker/statements.js +212 -20
  77. package/src/typechecker/stdlib/excluded.js +902 -0
  78. package/src/typechecker/stdlib/index.js +38 -0
  79. package/src/typechecker/stdlib/simd.js +65 -15
  80. package/src/typechecker/termination.js +11 -2
  81. package/src/typechecker/types.js +268 -514
  82. package/stdlib/bytes/buffer.go +479 -0
  83. package/stdlib/bytes/bytes.go +1010 -0
  84. package/stdlib/bytes/reader.go +161 -0
  85. package/stdlib/cmp/cmp.go +65 -0
  86. package/stdlib/context/context.go +115 -0
  87. package/stdlib/crypto/rand/rand.go +34 -0
  88. package/stdlib/crypto/sha256/sha256.go +249 -0
  89. package/stdlib/encoding/base64/base64.go +331 -0
  90. package/stdlib/encoding/binary/binary.go +332 -0
  91. package/stdlib/encoding/hex/hex.go +140 -0
  92. package/stdlib/encoding/json/errors.go +31 -0
  93. package/stdlib/encoding/json/indent.go +71 -0
  94. package/stdlib/encoding/json/json.go +62 -0
  95. package/stdlib/encoding/json/number.go +12 -0
  96. package/stdlib/encoding/json/stream.go +173 -0
  97. package/stdlib/errors/errors.go +174 -0
  98. package/stdlib/fmt/errors.go +110 -0
  99. package/stdlib/fmt/format.go +732 -0
  100. package/stdlib/fmt/print.go +1232 -0
  101. package/stdlib/gom/gom.go +293 -0
  102. package/stdlib/hash/hash.go +53 -0
  103. package/stdlib/html/html.go +251 -0
  104. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  105. package/stdlib/internal/jsonrt/dec.go +871 -0
  106. package/stdlib/internal/jsonrt/enc.go +516 -0
  107. package/stdlib/internal/jsonrt/indent.go +135 -0
  108. package/stdlib/internal/jsonrt/number.go +27 -0
  109. package/stdlib/internal/jsonrt/reader.go +73 -0
  110. package/stdlib/internal/jsonrt/scanner.go +658 -0
  111. package/stdlib/io/io.go +502 -0
  112. package/stdlib/iter/iter.go +18 -0
  113. package/stdlib/maps/maps.go +131 -0
  114. package/stdlib/math/bits/bits.go +507 -0
  115. package/stdlib/math/extra.go +272 -0
  116. package/stdlib/math/math.go +439 -0
  117. package/stdlib/math/rand/rand.go +297 -0
  118. package/stdlib/os/os.go +93 -0
  119. package/stdlib/path/filepath/filepath.go +47 -0
  120. package/stdlib/path/path.go +394 -0
  121. package/stdlib/regexp/regexp.go +231 -0
  122. package/stdlib/slices/slices.go +526 -0
  123. package/stdlib/slices/sort.go +209 -0
  124. package/stdlib/slices/zsort_cmp.go +480 -0
  125. package/stdlib/slices/zsort_ordered.go +482 -0
  126. package/stdlib/sort/sort.go +500 -0
  127. package/stdlib/sort/zsort_func.go +480 -0
  128. package/stdlib/sort/zsort_iface.go +480 -0
  129. package/stdlib/strconv/float.go +1699 -0
  130. package/stdlib/strconv/isprint.go +752 -0
  131. package/stdlib/strconv/quote.go +526 -0
  132. package/stdlib/strconv/strconv.go +616 -0
  133. package/stdlib/strings/builder.go +95 -0
  134. package/stdlib/strings/reader.go +163 -0
  135. package/stdlib/strings/replacer.go +102 -0
  136. package/stdlib/strings/strings.go +807 -0
  137. package/stdlib/sync/sync.go +268 -0
  138. package/stdlib/testing/async_js.go +61 -0
  139. package/stdlib/testing/benchmark.go +297 -0
  140. package/stdlib/testing/testing.go +523 -0
  141. package/stdlib/time/duration.go +233 -0
  142. package/stdlib/time/format.go +745 -0
  143. package/stdlib/time/parse.go +790 -0
  144. package/stdlib/time/sleep_js.go +63 -0
  145. package/stdlib/time/time.go +834 -0
  146. package/stdlib/unicode/unicode.go +250 -0
  147. package/stdlib/unicode/utf8/utf8.go +464 -0
  148. package/src/backend/js/stdlib/base64.js +0 -12
  149. package/src/backend/js/stdlib/binary.js +0 -102
  150. package/src/backend/js/stdlib/bits.js +0 -46
  151. package/src/backend/js/stdlib/builder.js +0 -63
  152. package/src/backend/js/stdlib/bytes.js +0 -122
  153. package/src/backend/js/stdlib/errors.js +0 -44
  154. package/src/backend/js/stdlib/fmt.js +0 -178
  155. package/src/backend/js/stdlib/gom.js +0 -155
  156. package/src/backend/js/stdlib/hex.js +0 -17
  157. package/src/backend/js/stdlib/html.js +0 -20
  158. package/src/backend/js/stdlib/io.js +0 -137
  159. package/src/backend/js/stdlib/json.js +0 -972
  160. package/src/backend/js/stdlib/maps.js +0 -45
  161. package/src/backend/js/stdlib/math.js +0 -69
  162. package/src/backend/js/stdlib/os.js +0 -13
  163. package/src/backend/js/stdlib/path.js +0 -48
  164. package/src/backend/js/stdlib/rand.js +0 -32
  165. package/src/backend/js/stdlib/regexp.js +0 -54
  166. package/src/backend/js/stdlib/sha256.js +0 -12
  167. package/src/backend/js/stdlib/shared.js +0 -17
  168. package/src/backend/js/stdlib/simd.js +0 -24
  169. package/src/backend/js/stdlib/slices.js +0 -77
  170. package/src/backend/js/stdlib/sort.js +0 -30
  171. package/src/backend/js/stdlib/strconv.js +0 -74
  172. package/src/backend/js/stdlib/strings.js +0 -222
  173. package/src/backend/js/stdlib/sync.js +0 -13
  174. package/src/backend/js/stdlib/testing.js +0 -34
  175. package/src/backend/js/stdlib/time.js +0 -128
  176. package/src/backend/js/stdlib/unicode.js +0 -25
  177. package/src/backend/js/stdlib/utf8.js +0 -26
  178. package/src/backend/wasm/const-fold.js +0 -205
  179. package/src/backend/wasm/emit-stdlib.js +0 -13
  180. package/src/backend/wasm/stdlib/bytes.js +0 -5039
  181. package/src/backend/wasm/stdlib/core.js +0 -8903
  182. package/src/backend/wasm/stdlib/io.js +0 -2161
  183. package/src/backend/wasm/stdlib/packages.js +0 -2400
  184. package/src/backend/wasm/stdlib/pure.js +0 -720
  185. package/src/backend/wasm/stdlib/time.js +0 -1200
  186. package/src/typechecker/stdlib/core.js +0 -801
  187. package/src/typechecker/stdlib/extended.js +0 -914
  188. package/src/typechecker/stdlib.js +0 -22
  189. /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
  190. /package/src/{colors.js → cli/colors.js} +0 -0
  191. /package/src/{dev-server.js → cli/dev-server.js} +0 -0
  192. /package/src/{minifier.js → cli/minifier.js} +0 -0
  193. /package/src/{project-config.js → cli/project-config.js} +0 -0
  194. /package/src/{pwa.js → cli/pwa.js} +0 -0
@@ -1,2161 +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
- emitIoConst(field, _targetWasmType) {
15
- if (field === "EOF") {
16
- this._emitLazyErrorGlobal(this.mod.getIoErrGlobalIndex("EOF"), "EOF");
17
- return;
18
- }
19
- if (field === "Discard") {
20
- const gIdx = this.mod.getIoDiscardGlobalIndex();
21
- const discardInfo = this.mod.getStructType("io.discard");
22
- this.pushInstruction({ op: "global.get", index: gIdx });
23
- this.pushInstruction("ref.is_null");
24
- this.pushInstruction({ op: "if", blockType: "void" });
25
- if (discardInfo) {
26
- this.pushInstruction({
27
- op: "struct.new",
28
- typeIndex: discardInfo.typeIndex,
29
- });
30
- } else {
31
- this.pushInstruction({ op: "ref.null", heapType: "any" });
32
- }
33
- this.pushInstruction({ op: "global.set", index: gIdx });
34
- this.pushInstruction("end");
35
- this.pushInstruction({ op: "global.get", index: gIdx });
36
- return;
37
- }
38
- throw new Error(`Unsupported io constant: ${field}`);
39
- }
40
-
41
- emitIoCall(name, call, targetWasmType) {
42
- if (name === "WriteString") {
43
- this._emitIoWriteString(call, targetWasmType);
44
- return;
45
- }
46
- if (name === "ReadAll") {
47
- this._emitIoReadAll(call, targetWasmType);
48
- return;
49
- }
50
- if (name === "LimitReader") {
51
- this._emitIoLimitReader(call, targetWasmType);
52
- return;
53
- }
54
- if (name === "Copy") {
55
- this._emitIoCopy(call, targetWasmType);
56
- return;
57
- }
58
- if (name === "CopyN") {
59
- this._emitIoCopyN(call, targetWasmType);
60
- return;
61
- }
62
- throw new Error(`Unsupported io call: ${name}`);
63
- }
64
-
65
- _emitIoWriteString(call, _targetWasmType) {
66
- const wExpr = call.args[0];
67
- const strExpr = call.args[1];
68
- const strTmp = this.acquireTemp("externref");
69
- this.emitExpr(strExpr, "externref");
70
- this.pushInstruction({ op: "local.set", index: strTmp });
71
- this._emitWriterWrite(wExpr, strTmp);
72
- this.releaseTemp(strTmp, "externref");
73
- }
74
-
75
- _emitWriterWrite(wExpr, strTmp) {
76
- const wType = wExpr._type ?? this._resolveExprGoType(wExpr);
77
- const targetName =
78
- wType?.name ?? (wType?.kind === "pointer" ? wType.base?.name : null);
79
- if (targetName === "strings.Builder") {
80
- const builderInfo = this.mod.getStructType("strings.Builder");
81
- const builderW = {
82
- kind: "ref",
83
- nullable: true,
84
- typeIndex: builderInfo.typeIndex,
85
- };
86
- const bTmp = this.acquireTemp(builderW);
87
- this.emitExpr(wExpr, builderW);
88
- this.pushInstruction({ op: "local.set", index: bTmp });
89
- this._emitBuilderWriteStringCore(bTmp, strTmp);
90
- this.releaseTemp(bTmp, builderW);
91
- return;
92
- }
93
- if (targetName === "bytes.Buffer") {
94
- const bufInfo = this.mod.getStructType("bytes.Buffer");
95
- const bufW = {
96
- kind: "ref",
97
- nullable: true,
98
- typeIndex: bufInfo.typeIndex,
99
- };
100
- const bTmp = this.acquireTemp(bufW);
101
- this.emitExpr(wExpr, bufW);
102
- this.pushInstruction({ op: "local.set", index: bTmp });
103
- this._emitBufferWriteStringCore(bTmp, strTmp);
104
- this.releaseTemp(bTmp, bufW);
105
- return;
106
- }
107
-
108
- const wTmp = this.acquireTemp("anyref");
109
- this.emitExpr(wExpr, "anyref");
110
- this.pushInstruction({ op: "local.set", index: wTmp });
111
-
112
- this.pushInstruction({ op: "local.get", index: wTmp });
113
- this.pushInstruction({ op: "local.get", index: strTmp });
114
- this._emitStringToByteSlice({ elem: { kind: "basic", name: "byte" } });
115
-
116
- const dispatchIdx = this.mod.resolveFuncIndex("__dispatch_io.Writer_Write");
117
- if (dispatchIdx !== null) {
118
- this.pushInstruction({ op: "call", funcIndex: dispatchIdx });
119
- } else {
120
- this.pushInstruction({ op: "i64.const", value: 0n });
121
- this.pushInstruction({ op: "ref.null", heapType: "any" });
122
- }
123
- this.releaseTemp(wTmp, "anyref");
124
- }
125
-
126
- _emitIoReadAll(call, _targetWasmType) {
127
- const rExpr = call.args[0];
128
- const rTmp = this.acquireTemp("anyref");
129
- this.emitExpr(rExpr, "anyref");
130
- this.pushInstruction({ op: "local.set", index: rTmp });
131
-
132
- const byteElemGo = { kind: "basic", name: "byte" };
133
- const sliceInfo = this.mod.getSliceType(byteElemGo);
134
- const arrInfo = sliceInfo.arrInfo;
135
- const sliceW = {
136
- kind: "ref",
137
- nullable: true,
138
- typeIndex: sliceInfo.typeIndex,
139
- };
140
- const arrW = { kind: "ref", nullable: true, typeIndex: arrInfo.typeIndex };
141
-
142
- // chunks slice (len: 0, cap: 512)
143
- const chunksTmp = this.acquireTemp(sliceW);
144
- this.pushInstruction({ op: "i32.const", value: 512 });
145
- this.pushInstruction({
146
- op: "array.new_default",
147
- typeIndex: arrInfo.typeIndex,
148
- });
149
- this.pushInstruction({ op: "i32.const", value: 0 });
150
- this.pushInstruction({ op: "i32.const", value: 0 });
151
- this.pushInstruction({ op: "i32.const", value: 512 });
152
- this.pushInstruction({
153
- op: "struct.new",
154
- typeIndex: sliceInfo.typeIndex,
155
- });
156
- this.pushInstruction({ op: "local.set", index: chunksTmp });
157
-
158
- // buf slice (len: 512, cap: 512)
159
- const bufTmp = this.acquireTemp(sliceW);
160
- this.pushInstruction({ op: "i32.const", value: 512 });
161
- this.pushInstruction({
162
- op: "array.new_default",
163
- typeIndex: arrInfo.typeIndex,
164
- });
165
- this.pushInstruction({ op: "i32.const", value: 0 });
166
- this.pushInstruction({ op: "i32.const", value: 512 });
167
- this.pushInstruction({ op: "i32.const", value: 512 });
168
- this.pushInstruction({
169
- op: "struct.new",
170
- typeIndex: sliceInfo.typeIndex,
171
- });
172
- this.pushInstruction({ op: "local.set", index: bufTmp });
173
-
174
- const errTmp = this.acquireTemp("anyref");
175
- this.pushInstruction({ op: "ref.null", heapType: "any" });
176
- this.pushInstruction({ op: "local.set", index: errTmp });
177
-
178
- const dispatchIdx = this.mod.resolveFuncIndex("__dispatch_io.Reader_Read");
179
-
180
- this.pushInstruction({ op: "block", blockType: "void" });
181
- this.pushInstruction({ op: "loop", blockType: "void" });
182
-
183
- this.pushInstruction({ op: "local.get", index: rTmp });
184
- this.pushInstruction({ op: "local.get", index: bufTmp });
185
- if (dispatchIdx !== null) {
186
- this.pushInstruction({ op: "call", funcIndex: dispatchIdx });
187
- } else {
188
- this.pushInstruction({ op: "i64.const", value: 0n });
189
- this.pushInstruction({ op: "ref.null", heapType: "any" });
190
- }
191
-
192
- // (n: i64, e: anyref)
193
- this.pushInstruction({ op: "local.set", index: errTmp });
194
- const nTmp = this.acquireTemp("i32");
195
- this.pushInstruction("i32.wrap_i64");
196
- this.pushInstruction({ op: "local.set", index: nTmp });
197
-
198
- // if n > 0, append buf[0:n] to chunks
199
- this.pushInstruction({ op: "local.get", index: nTmp });
200
- this.pushInstruction({ op: "i32.const", value: 0 });
201
- this.pushInstruction("i32.gt_s");
202
- this.pushInstruction({ op: "if", blockType: "void" });
203
- this._emitAppendSliceBytes(chunksTmp, bufTmp, nTmp, sliceInfo, arrW);
204
- this.pushInstruction("end");
205
- this.releaseTemp(nTmp, "i32");
206
-
207
- // if err != nil: if errors.Is(err, io.EOF) err = nil; break loop
208
- this.pushInstruction({ op: "local.get", index: errTmp });
209
- this.pushInstruction("ref.is_null");
210
- this.pushInstruction("i32.eqz");
211
- this.pushInstruction({ op: "if", blockType: "void" });
212
- this.pushInstruction({ op: "local.get", index: errTmp });
213
- this.emitIoConst("EOF", "anyref");
214
- this.pushInstruction({
215
- op: "call",
216
- funcIndex: this.mod.resolveFuncIndex("__errors_is"),
217
- });
218
- this.pushInstruction({ op: "if", blockType: "void" });
219
- this.pushInstruction({ op: "ref.null", heapType: "any" });
220
- this.pushInstruction({ op: "local.set", index: errTmp });
221
- this.pushInstruction("end");
222
- this.pushInstruction({ op: "br", depth: 2 });
223
- this.pushInstruction("end");
224
-
225
- this.pushInstruction({ op: "br", depth: 0 });
226
- this.pushInstruction("end");
227
- this.pushInstruction("end");
228
-
229
- this.pushInstruction({ op: "local.get", index: chunksTmp });
230
- this.pushInstruction({ op: "local.get", index: errTmp });
231
-
232
- this.releaseTemp(errTmp, "anyref");
233
- this.releaseTemp(bufTmp, sliceW);
234
- this.releaseTemp(chunksTmp, sliceW);
235
- this.releaseTemp(rTmp, "anyref");
236
- }
237
-
238
- _emitIoLimitReader(call, _targetWasmType) {
239
- const lrInfo = this.mod.getStructType("io.LimitedReader");
240
- if (!lrInfo) {
241
- throw new Error("io.LimitedReader struct type not found");
242
- }
243
- this.emitExpr(call.args[0], "anyref");
244
- this.emitExpr(call.args[1], "i64");
245
- this.pushInstruction({
246
- op: "struct.new",
247
- typeIndex: lrInfo.typeIndex,
248
- });
249
- }
250
-
251
- _emitIoCopy(call, _targetWasmType) {
252
- const dstTmp = this.acquireTemp("anyref");
253
- const srcTmp = this.acquireTemp("anyref");
254
- this.emitExpr(call.args[0], "anyref");
255
- this.pushInstruction({ op: "local.set", index: dstTmp });
256
- this.emitExpr(call.args[1], "anyref");
257
- this.pushInstruction({ op: "local.set", index: srcTmp });
258
-
259
- this._emitIoCopyCore(dstTmp, srcTmp);
260
-
261
- this.releaseTemp(srcTmp, "anyref");
262
- this.releaseTemp(dstTmp, "anyref");
263
- }
264
-
265
- _emitIoCopyN(call, _targetWasmType) {
266
- const lrInfo = this.mod.getStructType("io.LimitedReader");
267
- if (!lrInfo) {
268
- throw new Error("io.LimitedReader struct type not found");
269
- }
270
- const dstTmp = this.acquireTemp("anyref");
271
- const srcTmp = this.acquireTemp("anyref");
272
- const nTmp = this.acquireTemp("i64");
273
- this.emitExpr(call.args[0], "anyref");
274
- this.pushInstruction({ op: "local.set", index: dstTmp });
275
- this.emitExpr(call.args[1], "anyref");
276
- this.pushInstruction({ op: "local.set", index: srcTmp });
277
- this.emitExpr(call.args[2], "i64");
278
- this.pushInstruction({ op: "local.set", index: nTmp });
279
-
280
- const lrW = {
281
- kind: "ref",
282
- nullable: true,
283
- typeIndex: lrInfo.typeIndex,
284
- };
285
- const lrTmp = this.acquireTemp(lrW);
286
- this.pushInstruction({ op: "local.get", index: srcTmp });
287
- this.pushInstruction({ op: "local.get", index: nTmp });
288
- this.pushInstruction({
289
- op: "struct.new",
290
- typeIndex: lrInfo.typeIndex,
291
- });
292
- this.pushInstruction({ op: "local.set", index: lrTmp });
293
-
294
- this._emitIoCopyCore(dstTmp, lrTmp);
295
-
296
- const resErrTmp = this.acquireTemp("anyref");
297
- const writtenTmp = this.acquireTemp("i64");
298
- this.pushInstruction({ op: "local.set", index: resErrTmp });
299
- this.pushInstruction({ op: "local.set", index: writtenTmp });
300
-
301
- // if written == n: err = nil
302
- this.pushInstruction({ op: "local.get", index: writtenTmp });
303
- this.pushInstruction({ op: "local.get", index: nTmp });
304
- this.pushInstruction("i64.eq");
305
- this.pushInstruction({ op: "if", blockType: "void" });
306
- this.pushInstruction({ op: "ref.null", heapType: "any" });
307
- this.pushInstruction({ op: "local.set", index: resErrTmp });
308
- this.pushInstruction("else");
309
- // if written < n && resErr == nil: resErr = io.EOF
310
- this.pushInstruction({ op: "local.get", index: writtenTmp });
311
- this.pushInstruction({ op: "local.get", index: nTmp });
312
- this.pushInstruction("i64.lt_s");
313
- this.pushInstruction({ op: "local.get", index: resErrTmp });
314
- this.pushInstruction("ref.is_null");
315
- this.pushInstruction("i32.and");
316
- this.pushInstruction({ op: "if", blockType: "void" });
317
- this.emitIoConst("EOF", "anyref");
318
- this.pushInstruction({ op: "local.set", index: resErrTmp });
319
- this.pushInstruction("end");
320
- this.pushInstruction("end");
321
-
322
- this.pushInstruction({ op: "local.get", index: writtenTmp });
323
- this.pushInstruction({ op: "local.get", index: resErrTmp });
324
-
325
- this.releaseTemp(writtenTmp, "i64");
326
- this.releaseTemp(resErrTmp, "anyref");
327
- this.releaseTemp(lrTmp, lrW);
328
- this.releaseTemp(nTmp, "i64");
329
- this.releaseTemp(srcTmp, "anyref");
330
- this.releaseTemp(dstTmp, "anyref");
331
- }
332
-
333
- _emitIoCopyCore(dstTmp, srcTmp) {
334
- const byteElemGo = { kind: "basic", name: "byte" };
335
- const sliceInfo = this.mod.getSliceType(byteElemGo);
336
- const arrInfo = sliceInfo.arrInfo;
337
- const sliceW = {
338
- kind: "ref",
339
- nullable: true,
340
- typeIndex: sliceInfo.typeIndex,
341
- };
342
- const arrW = { kind: "ref", nullable: true, typeIndex: arrInfo.typeIndex };
343
-
344
- // Buffer: 32KB
345
- const bufSize = 32768;
346
- const bufArrTmp = this.acquireTemp(arrW);
347
- this.pushInstruction({ op: "i32.const", value: bufSize });
348
- this.pushInstruction({
349
- op: "array.new_default",
350
- typeIndex: arrInfo.typeIndex,
351
- });
352
- this.pushInstruction({ op: "local.set", index: bufArrTmp });
353
-
354
- const bufTmp = this.acquireTemp(sliceW);
355
- this.pushInstruction({ op: "local.get", index: bufArrTmp });
356
- this.pushInstruction({ op: "i32.const", value: 0 });
357
- this.pushInstruction({ op: "i32.const", value: bufSize });
358
- this.pushInstruction({ op: "i32.const", value: bufSize });
359
- this.pushInstruction({
360
- op: "struct.new",
361
- typeIndex: sliceInfo.typeIndex,
362
- });
363
- this.pushInstruction({ op: "local.set", index: bufTmp });
364
-
365
- const totalWrittenTmp = this.acquireTemp("i64");
366
- this.pushInstruction({ op: "i64.const", value: 0n });
367
- this.pushInstruction({ op: "local.set", index: totalWrittenTmp });
368
-
369
- const errTmp = this.acquireTemp("anyref");
370
- this.pushInstruction({ op: "ref.null", heapType: "any" });
371
- this.pushInstruction({ op: "local.set", index: errTmp });
372
-
373
- const readErrTmp = this.acquireTemp("anyref");
374
- const nrI32Tmp = this.acquireTemp("i32");
375
- const subsliceTmp = this.acquireTemp(sliceW);
376
- const writeErrTmp = this.acquireTemp("anyref");
377
- const nwTmp = this.acquireTemp("i64");
378
-
379
- const dispatchReadIdx = this.mod.resolveFuncIndex(
380
- "__dispatch_io.Reader_Read",
381
- );
382
- const dispatchWriteIdx = this.mod.resolveFuncIndex(
383
- "__dispatch_io.Writer_Write",
384
- );
385
-
386
- this.pushInstruction({ op: "block", blockType: "void" });
387
- this.pushInstruction({ op: "loop", blockType: "void" });
388
-
389
- // Read: src.Read(buf)
390
- this.pushInstruction({ op: "local.get", index: srcTmp });
391
- this.pushInstruction({ op: "local.get", index: bufTmp });
392
- if (dispatchReadIdx !== null) {
393
- this.pushInstruction({ op: "call", funcIndex: dispatchReadIdx });
394
- } else {
395
- this.pushInstruction({ op: "i64.const", value: 0n });
396
- this.pushInstruction({ op: "ref.null", heapType: "any" });
397
- }
398
- this.pushInstruction({ op: "local.set", index: readErrTmp });
399
- this.pushInstruction("i32.wrap_i64");
400
- this.pushInstruction({ op: "local.set", index: nrI32Tmp });
401
-
402
- // if nr > 0: write
403
- this.pushInstruction({ op: "local.get", index: nrI32Tmp });
404
- this.pushInstruction({ op: "i32.const", value: 0 });
405
- this.pushInstruction("i32.gt_s");
406
- this.pushInstruction({ op: "if", blockType: "void" });
407
-
408
- // subslice = slice(bufArrTmp, 0, nrI32Tmp, nrI32Tmp)
409
- this.pushInstruction({ op: "local.get", index: bufArrTmp });
410
- this.pushInstruction({ op: "i32.const", value: 0 });
411
- this.pushInstruction({ op: "local.get", index: nrI32Tmp });
412
- this.pushInstruction({ op: "local.get", index: nrI32Tmp });
413
- this.pushInstruction({
414
- op: "struct.new",
415
- typeIndex: sliceInfo.typeIndex,
416
- });
417
- this.pushInstruction({ op: "local.set", index: subsliceTmp });
418
-
419
- // dst.Write(subslice)
420
- this.pushInstruction({ op: "local.get", index: dstTmp });
421
- this.pushInstruction({ op: "local.get", index: subsliceTmp });
422
- if (dispatchWriteIdx !== null) {
423
- this.pushInstruction({ op: "call", funcIndex: dispatchWriteIdx });
424
- } else {
425
- this.pushInstruction({ op: "i64.const", value: 0n });
426
- this.pushInstruction({ op: "ref.null", heapType: "any" });
427
- }
428
- this.pushInstruction({ op: "local.set", index: writeErrTmp });
429
- this.pushInstruction({ op: "local.set", index: nwTmp });
430
-
431
- // totalWritten += nw
432
- this.pushInstruction({ op: "local.get", index: nwTmp });
433
- this.pushInstruction({ op: "i64.const", value: 0n });
434
- this.pushInstruction("i64.gt_s");
435
- this.pushInstruction({ op: "if", blockType: "void" });
436
- this.pushInstruction({ op: "local.get", index: totalWrittenTmp });
437
- this.pushInstruction({ op: "local.get", index: nwTmp });
438
- this.pushInstruction("i64.add");
439
- this.pushInstruction({ op: "local.set", index: totalWrittenTmp });
440
- this.pushInstruction("end");
441
-
442
- // if writeErr != nil: err = writeErr; br 2 (break loop)
443
- this.pushInstruction({ op: "local.get", index: writeErrTmp });
444
- this.pushInstruction("ref.is_null");
445
- this.pushInstruction("i32.eqz");
446
- this.pushInstruction({ op: "if", blockType: "void" });
447
- this.pushInstruction({ op: "local.get", index: writeErrTmp });
448
- this.pushInstruction({ op: "local.set", index: errTmp });
449
- this.pushInstruction({ op: "br", depth: 2 });
450
- this.pushInstruction("end");
451
-
452
- this.pushInstruction("end"); // end if nr > 0
453
-
454
- // if readErr != nil:
455
- this.pushInstruction({ op: "local.get", index: readErrTmp });
456
- this.pushInstruction("ref.is_null");
457
- this.pushInstruction("i32.eqz");
458
- this.pushInstruction({ op: "if", blockType: "void" });
459
- this.pushInstruction({ op: "local.get", index: readErrTmp });
460
- this.emitIoConst("EOF", "anyref");
461
- this.pushInstruction({
462
- op: "call",
463
- funcIndex: this.mod.resolveFuncIndex("__errors_is"),
464
- });
465
- this.pushInstruction({ op: "if", blockType: "void" });
466
- this.pushInstruction({ op: "ref.null", heapType: "any" });
467
- this.pushInstruction({ op: "local.set", index: errTmp });
468
- this.pushInstruction("else");
469
- this.pushInstruction({ op: "local.get", index: readErrTmp });
470
- this.pushInstruction({ op: "local.set", index: errTmp });
471
- this.pushInstruction("end");
472
- this.pushInstruction({ op: "br", depth: 2 }); // break loop
473
- this.pushInstruction("end"); // end if readErr != nil
474
-
475
- this.pushInstruction({ op: "br", depth: 0 }); // continue
476
- this.pushInstruction("end"); // end loop
477
- this.pushInstruction("end"); // end block
478
-
479
- this.pushInstruction({ op: "local.get", index: totalWrittenTmp });
480
- this.pushInstruction({ op: "local.get", index: errTmp });
481
-
482
- this.releaseTemp(nwTmp, "i64");
483
- this.releaseTemp(writeErrTmp, "anyref");
484
- this.releaseTemp(subsliceTmp, sliceW);
485
- this.releaseTemp(nrI32Tmp, "i32");
486
- this.releaseTemp(readErrTmp, "anyref");
487
- this.releaseTemp(errTmp, "anyref");
488
- this.releaseTemp(totalWrittenTmp, "i64");
489
- this.releaseTemp(bufTmp, sliceW);
490
- this.releaseTemp(bufArrTmp, arrW);
491
- }
492
-
493
- _emitAppendSliceBytes(dstSliceTmp, srcSliceTmp, countTmp, sliceInfo, arrW) {
494
- const arrInfo = sliceInfo.arrInfo;
495
- const byteGo = { kind: "basic", name: "byte" };
496
-
497
- const oldArrTmp = this.acquireTemp(arrW);
498
- const oldOffTmp = this.acquireTemp("i32");
499
- const oldLenTmp = this.acquireTemp("i32");
500
- const oldCapTmp = this.acquireTemp("i32");
501
- this._emitSliceUnpack(dstSliceTmp, sliceInfo, {
502
- arr: oldArrTmp,
503
- off: oldOffTmp,
504
- len: oldLenTmp,
505
- cap: oldCapTmp,
506
- });
507
-
508
- const newLenTmp = this.acquireTemp("i32");
509
- this.pushInstruction({ op: "local.get", index: oldLenTmp });
510
- this.pushInstruction({ op: "local.get", index: countTmp });
511
- this.pushInstruction("i32.add");
512
- this.pushInstruction({ op: "local.set", index: newLenTmp });
513
-
514
- const newArrTmp = this.acquireTemp(arrW);
515
- const newOffTmp = this.acquireTemp("i32");
516
- const newCapTmp = this.acquireTemp("i32");
517
- this._emitGrowSlice({
518
- arrInfo,
519
- elemGoType: byteGo,
520
- oldArrTmp,
521
- oldOffTmp,
522
- oldLenTmp,
523
- oldCapTmp,
524
- newArrTmp,
525
- newOffTmp,
526
- newLenTmp,
527
- newCapTmp,
528
- });
529
-
530
- const srcArrTmp = this.acquireTemp(arrW);
531
- const srcOffTmp = this.acquireTemp("i32");
532
- const srcLenTmp = this.acquireTemp("i32");
533
- const srcCapTmp = this.acquireTemp("i32");
534
- this._emitSliceUnpack(srcSliceTmp, sliceInfo, {
535
- arr: srcArrTmp,
536
- off: srcOffTmp,
537
- len: srcLenTmp,
538
- cap: srcCapTmp,
539
- });
540
- this.releaseTemp(srcCapTmp, "i32");
541
- this.releaseTemp(srcLenTmp, "i32");
542
-
543
- this.pushInstruction({ op: "local.get", index: newArrTmp });
544
- this.pushInstruction({ op: "local.get", index: newOffTmp });
545
- this.pushInstruction({ op: "local.get", index: oldLenTmp });
546
- this.pushInstruction("i32.add");
547
- this.pushInstruction({ op: "local.get", index: srcArrTmp });
548
- this.pushInstruction({ op: "local.get", index: srcOffTmp });
549
- this.pushInstruction({ op: "local.get", index: countTmp });
550
- this._emitArrayCopy(arrInfo, byteGo);
551
-
552
- this.releaseTemp(srcOffTmp, "i32");
553
- this.releaseTemp(srcArrTmp, arrW);
554
-
555
- this.pushInstruction({ op: "local.get", index: newArrTmp });
556
- this.pushInstruction({ op: "local.get", index: newOffTmp });
557
- this.pushInstruction({ op: "local.get", index: newLenTmp });
558
- this.pushInstruction({ op: "local.get", index: newCapTmp });
559
- this.pushInstruction({
560
- op: "struct.new",
561
- typeIndex: sliceInfo.typeIndex,
562
- });
563
- this.pushInstruction({ op: "local.set", index: dstSliceTmp });
564
-
565
- this.releaseTemp(newCapTmp, "i32");
566
- this.releaseTemp(newOffTmp, "i32");
567
- this.releaseTemp(newArrTmp, arrW);
568
- this.releaseTemp(newLenTmp, "i32");
569
- this.releaseTemp(oldCapTmp, "i32");
570
- this.releaseTemp(oldLenTmp, "i32");
571
- this.releaseTemp(oldOffTmp, "i32");
572
- this.releaseTemp(oldArrTmp, arrW);
573
- }
574
-
575
- emitStringsNewReader(call, _targetWasmType) {
576
- const structInfo = this.mod.getStructType("strings.Reader");
577
- this.emitExpr(call.args[0], "externref");
578
- this._emitStringToByteSlice({ elem: { kind: "basic", name: "byte" } });
579
- this.pushInstruction({ op: "i64.const", value: 0n });
580
- this.pushInstruction({
581
- op: "struct.new",
582
- typeIndex: structInfo.typeIndex,
583
- });
584
- }
585
-
586
- emitBytesNewReader(call, _targetWasmType) {
587
- const structInfo = this.mod.getStructType("bytes.Reader");
588
- const byteElemGo = { kind: "basic", name: "byte" };
589
- const sliceInfo = this.mod.getSliceType(byteElemGo);
590
- const sliceW = {
591
- kind: "ref",
592
- nullable: true,
593
- typeIndex: sliceInfo.typeIndex,
594
- };
595
- this.emitExpr(call.args[0], sliceW);
596
- this.pushInstruction({ op: "i64.const", value: 0n });
597
- this.pushInstruction({
598
- op: "struct.new",
599
- typeIndex: structInfo.typeIndex,
600
- });
601
- }
602
-
603
- emitStringsReaderMethodCall(method, expr, args, targetWasmType) {
604
- if (method === "Read") {
605
- this._emitStringsReaderRead(expr, args);
606
- return;
607
- }
608
- if (method === "Len") {
609
- this._emitStringsReaderLen(expr, targetWasmType);
610
- return;
611
- }
612
- if (method === "Reset") {
613
- this._emitStringsReaderReset(expr, args);
614
- return;
615
- }
616
- throw new Error(`Unsupported strings.Reader method: ${method}`);
617
- }
618
-
619
- _emitStringsReaderRead(expr, args) {
620
- const structInfo = this.mod.getStructType("strings.Reader");
621
- const readerW = {
622
- kind: "ref",
623
- nullable: true,
624
- typeIndex: structInfo.typeIndex,
625
- };
626
- const rTmp = this.acquireTemp(readerW);
627
- this.emitExpr(expr, readerW);
628
- this.pushInstruction({ op: "local.set", index: rTmp });
629
-
630
- const byteElemGo = { kind: "basic", name: "byte" };
631
- const sliceInfo = this.mod.getSliceType(byteElemGo);
632
- const sliceW = {
633
- kind: "ref",
634
- nullable: true,
635
- typeIndex: sliceInfo.typeIndex,
636
- };
637
- const pTmp = this.acquireTemp(sliceW);
638
- this.emitExpr(args[0], sliceW);
639
- this.pushInstruction({ op: "local.set", index: pTmp });
640
-
641
- this._emitStringsReaderReadCore(rTmp, pTmp);
642
- this.releaseTemp(pTmp, sliceW);
643
- this.releaseTemp(rTmp, readerW);
644
- }
645
-
646
- _emitReaderReadCore(typeName, rTmp, pTmp) {
647
- const structInfo = this.mod.getStructType(typeName);
648
- const byteElemGo = { kind: "basic", name: "byte" };
649
- const sliceInfo = this.mod.getSliceType(byteElemGo);
650
- const arrW = {
651
- kind: "ref",
652
- nullable: true,
653
- typeIndex: sliceInfo.arrInfo.typeIndex,
654
- };
655
-
656
- const pArrTmp = this.acquireTemp(arrW);
657
- const pOffTmp = this.acquireTemp("i32");
658
- const pLenTmp = this.acquireTemp("i32");
659
- const pCapTmp = this.acquireTemp("i32");
660
- this._emitSliceUnpack(pTmp, sliceInfo, {
661
- arr: pArrTmp,
662
- off: pOffTmp,
663
- len: pLenTmp,
664
- cap: pCapTmp,
665
- });
666
- this.releaseTemp(pCapTmp, "i32");
667
-
668
- const resNTmp = this.acquireTemp("i64");
669
- const resErrTmp = this.acquireTemp("anyref");
670
-
671
- // if p.len == 0: (0, nil)
672
- this.pushInstruction({ op: "local.get", index: pLenTmp });
673
- this.pushInstruction("i32.eqz");
674
- this.pushInstruction({ op: "if", blockType: "void" });
675
- this.pushInstruction({ op: "i64.const", value: 0n });
676
- this.pushInstruction({ op: "local.set", index: resNTmp });
677
- this.pushInstruction({ op: "ref.null", heapType: "any" });
678
- this.pushInstruction({ op: "local.set", index: resErrTmp });
679
- this.pushInstruction("else");
680
-
681
- const srcSliceW = {
682
- kind: "ref",
683
- nullable: true,
684
- typeIndex: sliceInfo.typeIndex,
685
- };
686
- const srcSliceTmp = this.acquireTemp(srcSliceW);
687
- this.pushInstruction({ op: "local.get", index: rTmp });
688
- this.pushInstruction({
689
- op: "struct.get",
690
- typeIndex: structInfo.typeIndex,
691
- fieldIndex: 0,
692
- });
693
- this.pushInstruction({ op: "local.set", index: srcSliceTmp });
694
-
695
- const srcArrTmp = this.acquireTemp(arrW);
696
- const srcOffTmp = this.acquireTemp("i32");
697
- const srcLenTmp = this.acquireTemp("i32");
698
- const srcCapTmp = this.acquireTemp("i32");
699
- this._emitSliceUnpack(srcSliceTmp, sliceInfo, {
700
- arr: srcArrTmp,
701
- off: srcOffTmp,
702
- len: srcLenTmp,
703
- cap: srcCapTmp,
704
- });
705
- this.releaseTemp(srcCapTmp, "i32");
706
- this.releaseTemp(srcSliceTmp, srcSliceW);
707
-
708
- const posTmp = this.acquireTemp("i64");
709
- this.pushInstruction({ op: "local.get", index: rTmp });
710
- this.pushInstruction({
711
- op: "struct.get",
712
- typeIndex: structInfo.typeIndex,
713
- fieldIndex: 1,
714
- });
715
- this.pushInstruction({ op: "local.set", index: posTmp });
716
-
717
- // if pos >= srcLen: (0, io.EOF)
718
- this.pushInstruction({ op: "local.get", index: posTmp });
719
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
720
- this.pushInstruction("i64.extend_i32_u");
721
- this.pushInstruction("i64.ge_s");
722
- this.pushInstruction({ op: "if", blockType: "void" });
723
- this.pushInstruction({ op: "i64.const", value: 0n });
724
- this.pushInstruction({ op: "local.set", index: resNTmp });
725
- this.emitIoConst("EOF", "anyref");
726
- this.pushInstruction({ op: "local.set", index: resErrTmp });
727
- this.pushInstruction("else");
728
-
729
- // avail = srcLen - pos
730
- const availTmp = this.acquireTemp("i32");
731
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
732
- this.pushInstruction({ op: "local.get", index: posTmp });
733
- this.pushInstruction("i32.wrap_i64");
734
- this.pushInstruction("i32.sub");
735
- this.pushInstruction({ op: "local.set", index: availTmp });
736
-
737
- // n = min(p.len, avail)
738
- const nTmp = this.acquireTemp("i32");
739
- this.pushInstruction({ op: "local.get", index: pLenTmp });
740
- this.pushInstruction({ op: "local.get", index: availTmp });
741
- this.pushInstruction("i32.lt_s");
742
- this.pushInstruction({ op: "if", blockType: "i32" });
743
- this.pushInstruction({ op: "local.get", index: pLenTmp });
744
- this.pushInstruction("else");
745
- this.pushInstruction({ op: "local.get", index: availTmp });
746
- this.pushInstruction("end");
747
- this.pushInstruction({ op: "local.set", index: nTmp });
748
-
749
- // copy bytes: p.arr[p.off] = src.arr[src.off + pos]
750
- this.pushInstruction({ op: "local.get", index: pArrTmp });
751
- this.pushInstruction({ op: "local.get", index: pOffTmp });
752
- this.pushInstruction({ op: "local.get", index: srcArrTmp });
753
- this.pushInstruction({ op: "local.get", index: srcOffTmp });
754
- this.pushInstruction({ op: "local.get", index: posTmp });
755
- this.pushInstruction("i32.wrap_i64");
756
- this.pushInstruction("i32.add");
757
- this.pushInstruction({ op: "local.get", index: nTmp });
758
- this._emitArrayCopy(sliceInfo.arrInfo, byteElemGo);
759
-
760
- // r._pos += n
761
- this.pushInstruction({ op: "local.get", index: rTmp });
762
- this.pushInstruction({ op: "local.get", index: posTmp });
763
- this.pushInstruction({ op: "local.get", index: nTmp });
764
- this.pushInstruction("i64.extend_i32_u");
765
- this.pushInstruction("i64.add");
766
- this.pushInstruction({
767
- op: "struct.set",
768
- typeIndex: structInfo.typeIndex,
769
- fieldIndex: 1,
770
- });
771
-
772
- this.pushInstruction({ op: "local.get", index: nTmp });
773
- this.pushInstruction("i64.extend_i32_u");
774
- this.pushInstruction({ op: "local.set", index: resNTmp });
775
- this.pushInstruction({ op: "ref.null", heapType: "any" });
776
- this.pushInstruction({ op: "local.set", index: resErrTmp });
777
-
778
- this.releaseTemp(nTmp, "i32");
779
- this.releaseTemp(availTmp, "i32");
780
- this.pushInstruction("end");
781
- this.releaseTemp(posTmp, "i64");
782
- this.releaseTemp(srcLenTmp, "i32");
783
- this.releaseTemp(srcOffTmp, "i32");
784
- this.releaseTemp(srcArrTmp, arrW);
785
- this.pushInstruction("end");
786
-
787
- this.pushInstruction({ op: "local.get", index: resNTmp });
788
- this.pushInstruction({ op: "local.get", index: resErrTmp });
789
-
790
- this.releaseTemp(resErrTmp, "anyref");
791
- this.releaseTemp(resNTmp, "i64");
792
- this.releaseTemp(pLenTmp, "i32");
793
- this.releaseTemp(pOffTmp, "i32");
794
- this.releaseTemp(pArrTmp, arrW);
795
- }
796
-
797
- _emitReaderLenCore(typeName, rTmp, targetWasmType) {
798
- const structInfo = this.mod.getStructType(typeName);
799
- const byteElemGo = { kind: "basic", name: "byte" };
800
- const sliceInfo = this.mod.getSliceType(byteElemGo);
801
-
802
- this.pushInstruction({ op: "local.get", index: rTmp });
803
- this.pushInstruction({
804
- op: "struct.get",
805
- typeIndex: structInfo.typeIndex,
806
- fieldIndex: 0,
807
- });
808
- this.pushInstruction({
809
- op: "struct.get",
810
- typeIndex: sliceInfo.typeIndex,
811
- fieldIndex: 2,
812
- });
813
- this.pushInstruction("i64.extend_i32_u");
814
- this.pushInstruction({ op: "local.get", index: rTmp });
815
- this.pushInstruction({
816
- op: "struct.get",
817
- typeIndex: structInfo.typeIndex,
818
- fieldIndex: 1,
819
- });
820
- this.pushInstruction("i64.sub");
821
- const resTmp = this.acquireTemp("i64");
822
- this.pushInstruction({ op: "local.set", index: resTmp });
823
-
824
- this.pushInstruction({ op: "local.get", index: resTmp });
825
- this.pushInstruction({ op: "i64.const", value: 0n });
826
- this.pushInstruction("i64.lt_s");
827
- this.pushInstruction({ op: "if", blockType: "i64" });
828
- this.pushInstruction({ op: "i64.const", value: 0n });
829
- this.pushInstruction("else");
830
- this.pushInstruction({ op: "local.get", index: resTmp });
831
- this.pushInstruction("end");
832
- if ((targetWasmType ?? "i64") === "i32") {
833
- this.pushInstruction("i32.wrap_i64");
834
- }
835
- this.releaseTemp(resTmp, "i64");
836
- }
837
-
838
- _emitStringsReaderReadCore(rTmp, pTmp) {
839
- this._emitReaderReadCore("strings.Reader", rTmp, pTmp);
840
- }
841
-
842
- _emitStringsReaderLen(expr, targetWasmType) {
843
- const structInfo = this.mod.getStructType("strings.Reader");
844
- const readerW = {
845
- kind: "ref",
846
- nullable: true,
847
- typeIndex: structInfo.typeIndex,
848
- };
849
- const rTmp = this.acquireTemp(readerW);
850
- this.emitExpr(expr, readerW);
851
- this.pushInstruction({ op: "local.set", index: rTmp });
852
-
853
- this._emitStringsReaderLenCore(rTmp, targetWasmType);
854
- this.releaseTemp(rTmp, readerW);
855
- }
856
-
857
- _emitStringsReaderLenCore(rTmp, targetWasmType) {
858
- this._emitReaderLenCore("strings.Reader", rTmp, targetWasmType);
859
- }
860
-
861
- _emitStringsReaderReset(expr, args) {
862
- const structInfo = this.mod.getStructType("strings.Reader");
863
- const readerW = {
864
- kind: "ref",
865
- nullable: true,
866
- typeIndex: structInfo.typeIndex,
867
- };
868
- const rTmp = this.acquireTemp(readerW);
869
- this.emitExpr(expr, readerW);
870
- this.pushInstruction({ op: "local.set", index: rTmp });
871
-
872
- const sTmp = this.acquireTemp("externref");
873
- this.emitExpr(args[0], "externref");
874
- this.pushInstruction({ op: "local.set", index: sTmp });
875
-
876
- this._emitStringsReaderResetCore(rTmp, sTmp);
877
- this.releaseTemp(sTmp, "externref");
878
- this.releaseTemp(rTmp, readerW);
879
- }
880
-
881
- _emitStringsReaderResetCore(rTmp, sTmp) {
882
- const structInfo = this.mod.getStructType("strings.Reader");
883
- this.pushInstruction({ op: "local.get", index: rTmp });
884
- this.pushInstruction({ op: "local.get", index: sTmp });
885
- this._emitStringToByteSlice({ elem: { kind: "basic", name: "byte" } });
886
- this.pushInstruction({
887
- op: "struct.set",
888
- typeIndex: structInfo.typeIndex,
889
- fieldIndex: 0,
890
- });
891
- this.pushInstruction({ op: "local.get", index: rTmp });
892
- this.pushInstruction({ op: "i64.const", value: 0n });
893
- this.pushInstruction({
894
- op: "struct.set",
895
- typeIndex: structInfo.typeIndex,
896
- fieldIndex: 1,
897
- });
898
- }
899
-
900
- emitBytesReaderMethodCall(method, expr, args, targetWasmType) {
901
- if (method === "Read") {
902
- this._emitBytesReaderRead(expr, args);
903
- return;
904
- }
905
- if (method === "Len") {
906
- this._emitBytesReaderLen(expr, targetWasmType);
907
- return;
908
- }
909
- if (method === "Reset") {
910
- this._emitBytesReaderReset(expr, args);
911
- return;
912
- }
913
- throw new Error(`Unsupported bytes.Reader method: ${method}`);
914
- }
915
-
916
- _emitBytesReaderRead(expr, args) {
917
- const structInfo = this.mod.getStructType("bytes.Reader");
918
- const readerW = {
919
- kind: "ref",
920
- nullable: true,
921
- typeIndex: structInfo.typeIndex,
922
- };
923
- const rTmp = this.acquireTemp(readerW);
924
- this.emitExpr(expr, readerW);
925
- this.pushInstruction({ op: "local.set", index: rTmp });
926
-
927
- const byteElemGo = { kind: "basic", name: "byte" };
928
- const sliceInfo = this.mod.getSliceType(byteElemGo);
929
- const sliceW = {
930
- kind: "ref",
931
- nullable: true,
932
- typeIndex: sliceInfo.typeIndex,
933
- };
934
- const pTmp = this.acquireTemp(sliceW);
935
- this.emitExpr(args[0], sliceW);
936
- this.pushInstruction({ op: "local.set", index: pTmp });
937
-
938
- this._emitBytesReaderReadCore(rTmp, pTmp);
939
- this.releaseTemp(pTmp, sliceW);
940
- this.releaseTemp(rTmp, readerW);
941
- }
942
-
943
- _emitBytesReaderReadCore(rTmp, pTmp) {
944
- this._emitReaderReadCore("bytes.Reader", rTmp, pTmp);
945
- }
946
-
947
- _emitBytesReaderLen(expr, targetWasmType) {
948
- const structInfo = this.mod.getStructType("bytes.Reader");
949
- const readerW = {
950
- kind: "ref",
951
- nullable: true,
952
- typeIndex: structInfo.typeIndex,
953
- };
954
- const rTmp = this.acquireTemp(readerW);
955
- this.emitExpr(expr, readerW);
956
- this.pushInstruction({ op: "local.set", index: rTmp });
957
-
958
- this._emitBytesReaderLenCore(rTmp, targetWasmType);
959
- this.releaseTemp(rTmp, readerW);
960
- }
961
-
962
- _emitBytesReaderLenCore(rTmp, targetWasmType) {
963
- this._emitReaderLenCore("bytes.Reader", rTmp, targetWasmType);
964
- }
965
-
966
- _emitBytesReaderReset(expr, args) {
967
- const structInfo = this.mod.getStructType("bytes.Reader");
968
- const readerW = {
969
- kind: "ref",
970
- nullable: true,
971
- typeIndex: structInfo.typeIndex,
972
- };
973
- const rTmp = this.acquireTemp(readerW);
974
- this.emitExpr(expr, readerW);
975
- this.pushInstruction({ op: "local.set", index: rTmp });
976
-
977
- const byteElemGo = { kind: "basic", name: "byte" };
978
- const sliceInfo = this.mod.getSliceType(byteElemGo);
979
- const sliceW = {
980
- kind: "ref",
981
- nullable: true,
982
- typeIndex: sliceInfo.typeIndex,
983
- };
984
- const bTmp = this.acquireTemp(sliceW);
985
- this.emitExpr(args[0], sliceW);
986
- this.pushInstruction({ op: "local.set", index: bTmp });
987
-
988
- this._emitBytesReaderResetCore(rTmp, bTmp);
989
- this.releaseTemp(bTmp, sliceW);
990
- this.releaseTemp(rTmp, readerW);
991
- }
992
-
993
- _emitBytesReaderResetCore(rTmp, bTmp) {
994
- const structInfo = this.mod.getStructType("bytes.Reader");
995
- this.pushInstruction({ op: "local.get", index: rTmp });
996
- this.pushInstruction({ op: "local.get", index: bTmp });
997
- this.pushInstruction({
998
- op: "struct.set",
999
- typeIndex: structInfo.typeIndex,
1000
- fieldIndex: 0,
1001
- });
1002
- this.pushInstruction({ op: "local.get", index: rTmp });
1003
- this.pushInstruction({ op: "i64.const", value: 0n });
1004
- this.pushInstruction({
1005
- op: "struct.set",
1006
- typeIndex: structInfo.typeIndex,
1007
- fieldIndex: 1,
1008
- });
1009
- }
1010
-
1011
- emitFprintCall(fn, call, _targetWasmType) {
1012
- const wExpr = call.args[0];
1013
- const strTmp = this.acquireTemp("externref");
1014
- this._emitFprintFormatString(fn, call.args.slice(1));
1015
- this.pushInstruction({ op: "local.set", index: strTmp });
1016
-
1017
- const wType = wExpr._type;
1018
- const targetName =
1019
- wType?.name ?? (wType?.kind === "pointer" ? wType.base?.name : null);
1020
- if (targetName === "strings.Builder") {
1021
- // Builder.WriteString
1022
- const builderInfo = this.mod.getStructType("strings.Builder");
1023
- const builderW = {
1024
- kind: "ref",
1025
- nullable: true,
1026
- typeIndex: builderInfo.typeIndex,
1027
- };
1028
- const bTmp = this.acquireTemp(builderW);
1029
- this.emitExpr(wExpr, builderW);
1030
- this.pushInstruction({ op: "local.set", index: bTmp });
1031
- this._emitBuilderWriteStringCore(bTmp, strTmp);
1032
- this.releaseTemp(bTmp, builderW);
1033
- this.releaseTemp(strTmp, "externref");
1034
- return;
1035
- }
1036
- if (targetName === "bytes.Buffer") {
1037
- const bufInfo = this.mod.getStructType("bytes.Buffer");
1038
- const bufW = {
1039
- kind: "ref",
1040
- nullable: true,
1041
- typeIndex: bufInfo.typeIndex,
1042
- };
1043
- const bTmp = this.acquireTemp(bufW);
1044
- this.emitExpr(wExpr, bufW);
1045
- this.pushInstruction({ op: "local.set", index: bTmp });
1046
- this._emitBufferWriteStringCore(bTmp, strTmp);
1047
- this.releaseTemp(bTmp, bufW);
1048
- this.releaseTemp(strTmp, "externref");
1049
- return;
1050
- }
1051
-
1052
- this._emitWriterWrite(wExpr, strTmp);
1053
- this.releaseTemp(strTmp, "externref");
1054
- }
1055
-
1056
- _emitFprintFormatString(fn, restArgs) {
1057
- if (fn === "Fprintf") {
1058
- const [format, ...rest] = restArgs;
1059
- const temps = this._emitArgBuffer(rest);
1060
- this.emitExpr(format, "externref");
1061
- this._callStdlib("fmt_sprintf");
1062
- this._releaseArgBuffer(temps);
1063
- return;
1064
- }
1065
- const argc = restArgs.length;
1066
- if (argc === 0) {
1067
- const s = fn === "Fprintln" ? "\n" : "";
1068
- const strIdx = this.mod.internString(s);
1069
- this.pushInstruction({ op: "i32.const", value: strIdx });
1070
- this.pushInstruction({
1071
- op: "call",
1072
- funcIndex: this.mod.getStringImportIndex(),
1073
- });
1074
- return;
1075
- }
1076
- const sep = fn === "Fprintln" ? " " : "";
1077
- const suffix = fn === "Fprintln" ? "\n" : "";
1078
- const fmt = Array(argc).fill("%v").join(sep) + suffix;
1079
- const temps = this._emitArgBuffer(restArgs);
1080
- const strIdx = this.mod.internString(fmt);
1081
- this.pushInstruction({ op: "i32.const", value: strIdx });
1082
- this.pushInstruction({
1083
- op: "call",
1084
- funcIndex: this.mod.getStringImportIndex(),
1085
- });
1086
- this._callStdlib("fmt_sprintf");
1087
- this._releaseArgBuffer(temps);
1088
- }
1089
-
1090
- emitSscanCall(fn, call, _targetWasmType) {
1091
- const strArg = call.args[0];
1092
- const mode = fn === "Sscanln" ? 1 : 0;
1093
- const ptrs = fn === "Sscanf" ? call.args.slice(2) : call.args.slice(1);
1094
-
1095
- if (fn === "Sscanf") {
1096
- this.emitExpr(strArg, "externref");
1097
- this.emitExpr(call.args[1], "externref");
1098
- this._callStdlib("fmt_sscanf_init");
1099
- } else {
1100
- this.emitExpr(strArg, "externref");
1101
- this.pushInstruction({ op: "i32.const", value: mode });
1102
- this._callStdlib("fmt_sscan_init");
1103
- }
1104
- const totTokensTmp = this.acquireTemp("i32");
1105
- this.pushInstruction({ op: "local.set", index: totTokensTmp });
1106
-
1107
- const nTmp = this.acquireTemp("i64");
1108
- this.pushInstruction({ op: "i64.const", value: 0n });
1109
- this.pushInstruction({ op: "local.set", index: nTmp });
1110
-
1111
- for (let i = 0; i < ptrs.length; i++) {
1112
- this._emitSscanAssignOne(ptrs[i], i, totTokensTmp, nTmp);
1113
- }
1114
-
1115
- // return (n: i64, err: anyref)
1116
- this.pushInstruction({ op: "local.get", index: nTmp });
1117
-
1118
- this._callStdlib("fmt_sscan_has_err");
1119
- this.pushInstruction({ op: "if", blockType: "anyref" });
1120
- this._callStdlib("fmt_sscan_err_msg");
1121
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1122
- this.pushInstruction({
1123
- op: "call",
1124
- funcIndex: this.mod.resolveFuncIndex("__mk_error"),
1125
- });
1126
- this.pushInstruction("else");
1127
- this.pushInstruction({ op: "local.get", index: nTmp });
1128
- this.pushInstruction({ op: "i64.const", value: BigInt(ptrs.length) });
1129
- this.pushInstruction("i64.lt_s");
1130
- this.pushInstruction({ op: "if", blockType: "anyref" });
1131
- const strIdx = this.mod.internString("unexpected EOF");
1132
- this.pushInstruction({ op: "i32.const", value: strIdx });
1133
- this.pushInstruction({
1134
- op: "call",
1135
- funcIndex: this.mod.getStringImportIndex(),
1136
- });
1137
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1138
- this.pushInstruction({
1139
- op: "call",
1140
- funcIndex: this.mod.resolveFuncIndex("__mk_error"),
1141
- });
1142
- this.pushInstruction("else");
1143
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1144
- this.pushInstruction("end");
1145
- this.pushInstruction("end");
1146
-
1147
- this.releaseTemp(nTmp, "i64");
1148
- this.releaseTemp(totTokensTmp, "i32");
1149
- }
1150
-
1151
- _emitSscanAssignOne(pExpr, tokenIdx, totTokensTmp, nTmp) {
1152
- this.pushInstruction({ op: "i32.const", value: tokenIdx });
1153
- this.pushInstruction({ op: "local.get", index: totTokensTmp });
1154
- this.pushInstruction("i32.lt_s");
1155
- this.pushInstruction({ op: "if", blockType: "void" });
1156
-
1157
- this._callStdlib("fmt_sscan_has_err");
1158
- this.pushInstruction({ op: "if", blockType: "void" });
1159
- this.pushInstruction("else");
1160
-
1161
- this._emitSscanWriteToken(pExpr, tokenIdx);
1162
-
1163
- this._callStdlib("fmt_sscan_has_err");
1164
- this.pushInstruction({ op: "if", blockType: "void" });
1165
- this.pushInstruction("else");
1166
- this.pushInstruction({ op: "local.get", index: nTmp });
1167
- this.pushInstruction({ op: "i64.const", value: 1n });
1168
- this.pushInstruction("i64.add");
1169
- this.pushInstruction({ op: "local.set", index: nTmp });
1170
- this.pushInstruction("end");
1171
-
1172
- this.pushInstruction("end");
1173
- this.pushInstruction("end");
1174
- }
1175
-
1176
- _emitSscanWriteToken(pExpr, tokenIdx) {
1177
- const isAddressOf = pExpr.kind === "UnaryExpr" && pExpr.op === "&";
1178
- const pType =
1179
- pExpr._type ??
1180
- (pExpr.kind === "Ident" ? this.resolveLocal(pExpr.name)?.goType : null) ??
1181
- this._resolveExprGoType(pExpr);
1182
- const pointeeType = pType?.base ?? pType;
1183
- const targetNode = isAddressOf
1184
- ? (pExpr.operand ?? pExpr.expr)
1185
- : {
1186
- kind: "UnaryExpr",
1187
- op: "*",
1188
- operand: { ...pExpr, _type: pType },
1189
- _type: pointeeType,
1190
- };
1191
- const effectivePointee = targetNode._type ?? pointeeType;
1192
- const wType = toWasmType(effectivePointee, this.mod.checker, this.mod);
1193
-
1194
- this._emitAssignToTarget(targetNode, wType, effectivePointee, () => {
1195
- this._emitSscanTokenValue(wType, effectivePointee, tokenIdx);
1196
- });
1197
- }
1198
-
1199
- _emitSscanTokenValue(wType, pointeeType, tokenIdx) {
1200
- this.pushInstruction({ op: "i32.const", value: tokenIdx });
1201
- if (wType === "i64") {
1202
- this._callStdlib("fmt_sscan_token_i64");
1203
- return;
1204
- }
1205
- if (wType === "i32") {
1206
- if (pointeeType?.name === "bool") {
1207
- this._callStdlib("fmt_sscan_token_bool");
1208
- } else {
1209
- this._callStdlib("fmt_sscan_token_i64");
1210
- this.pushInstruction("i32.wrap_i64");
1211
- }
1212
- return;
1213
- }
1214
- if (wType === "f64") {
1215
- this._callStdlib("fmt_sscan_token_f64");
1216
- return;
1217
- }
1218
- if (wType === "f32") {
1219
- this._callStdlib("fmt_sscan_token_f64");
1220
- this.pushInstruction("f32.demote_f64");
1221
- return;
1222
- }
1223
- if (wType === "externref") {
1224
- this._callStdlib("fmt_sscan_token_str");
1225
- return;
1226
- }
1227
- this._callStdlib("fmt_sscan_token_str");
1228
- }
1229
-
1230
- emitIoHelper(fn) {
1231
- const kind = fn._isIoHelper ?? fn._isPhase7Helper;
1232
- switch (kind) {
1233
- case "builder_write":
1234
- this._emitHelperBuilderWrite(fn);
1235
- return;
1236
- case "builder_write_string":
1237
- this._emitHelperBuilderWriteString(fn);
1238
- return;
1239
- case "buffer_write":
1240
- this._emitHelperBufferWrite(fn);
1241
- return;
1242
- case "buffer_write_string":
1243
- this._emitHelperBufferWriteString(fn);
1244
- return;
1245
- case "buffer_read":
1246
- this._emitHelperBufferRead(fn);
1247
- return;
1248
- case "strings_reader_read":
1249
- this._emitHelperStringsReaderRead(fn);
1250
- return;
1251
- case "strings_reader_len":
1252
- this._emitHelperStringsReaderLen(fn);
1253
- return;
1254
- case "strings_reader_reset":
1255
- this._emitHelperStringsReaderReset(fn);
1256
- return;
1257
- case "bytes_reader_read":
1258
- this._emitHelperBytesReaderRead(fn);
1259
- return;
1260
- case "bytes_reader_len":
1261
- this._emitHelperBytesReaderLen(fn);
1262
- return;
1263
- case "bytes_reader_reset":
1264
- this._emitHelperBytesReaderReset(fn);
1265
- return;
1266
- case "discard_write":
1267
- this._emitHelperDiscardWrite(fn);
1268
- return;
1269
- case "discard_write_string":
1270
- this._emitHelperDiscardWriteString(fn);
1271
- return;
1272
- case "limited_reader_read":
1273
- this._emitHelperLimitedReaderRead(fn);
1274
- return;
1275
- case "sha256_write":
1276
- this._emitHelperSha256Write(fn);
1277
- return;
1278
- case "sha256_sum":
1279
- this._emitHelperSha256Sum(fn);
1280
- return;
1281
- case "sha256_reset":
1282
- this._emitHelperSha256Reset(fn);
1283
- return;
1284
- case "sha256_size":
1285
- this._emitHelperSha256Size(fn);
1286
- return;
1287
- case "sha256_block_size":
1288
- this._emitHelperSha256BlockSize(fn);
1289
- return;
1290
- default:
1291
- throw new Error(`Unknown io helper: ${kind}`);
1292
- }
1293
- }
1294
-
1295
- emitPhase7Helper(fn) {
1296
- return this.emitIoHelper(fn);
1297
- }
1298
-
1299
- _emitHelperBuilderWrite(_fn) {
1300
- this._emitBuilderWriteCore(0, 1);
1301
- this.pushInstruction("return");
1302
- }
1303
-
1304
- _emitHelperBuilderWriteString(_fn) {
1305
- this._emitBuilderWriteStringCore(0, 1);
1306
- this.pushInstruction("return");
1307
- }
1308
-
1309
- _emitBuilderWriteCore(bTmp, pTmp) {
1310
- const byteElemGo = { kind: "basic", name: "byte" };
1311
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1312
- const arrW = {
1313
- kind: "ref",
1314
- nullable: true,
1315
- typeIndex: sliceInfo.arrInfo.typeIndex,
1316
- };
1317
-
1318
- const pArrTmp = this.acquireTemp(arrW);
1319
- const pOffTmp = this.acquireTemp("i32");
1320
- const pLenTmp = this.acquireTemp("i32");
1321
- const pCapTmp = this.acquireTemp("i32");
1322
- this._emitSliceUnpack(pTmp, sliceInfo, {
1323
- arr: pArrTmp,
1324
- off: pOffTmp,
1325
- len: pLenTmp,
1326
- cap: pCapTmp,
1327
- });
1328
- this.releaseTemp(pCapTmp, "i32");
1329
-
1330
- this.pushInstruction({ op: "local.get", index: pLenTmp });
1331
- this._callStdlib("bytes_to_str_init");
1332
-
1333
- const kTmp = this.acquireTemp("i32");
1334
- this.pushInstruction({ op: "i32.const", value: 0 });
1335
- this.pushInstruction({ op: "local.set", index: kTmp });
1336
-
1337
- this.pushInstruction({ op: "block", blockType: "void" });
1338
- this.pushInstruction({ op: "loop", blockType: "void" });
1339
- this.pushInstruction({ op: "local.get", index: kTmp });
1340
- this.pushInstruction({ op: "local.get", index: pLenTmp });
1341
- this.pushInstruction("i32.ge_s");
1342
- this.pushInstruction({ op: "br_if", depth: 1 });
1343
-
1344
- this.pushInstruction({ op: "local.get", index: pArrTmp });
1345
- this.pushInstruction({ op: "local.get", index: pOffTmp });
1346
- this.pushInstruction({ op: "local.get", index: kTmp });
1347
- this.pushInstruction("i32.add");
1348
- this.pushInstruction({
1349
- op: "array.get",
1350
- typeIndex: sliceInfo.arrInfo.typeIndex,
1351
- });
1352
- this._callStdlib("bytes_to_str_push");
1353
-
1354
- this.pushInstruction({ op: "local.get", index: kTmp });
1355
- this.pushInstruction({ op: "i32.const", value: 1 });
1356
- this.pushInstruction("i32.add");
1357
- this.pushInstruction({ op: "local.set", index: kTmp });
1358
- this.pushInstruction({ op: "br", depth: 0 });
1359
- this.pushInstruction("end");
1360
- this.pushInstruction("end");
1361
-
1362
- this._callStdlib("bytes_to_str_finish");
1363
- const strTmp = this.acquireTemp("externref");
1364
- this.pushInstruction({ op: "local.set", index: strTmp });
1365
-
1366
- this._emitBuilderWriteStringCore(bTmp, strTmp);
1367
- this.releaseTemp(strTmp, "externref");
1368
- this.releaseTemp(kTmp, "i32");
1369
- this.releaseTemp(pLenTmp, "i32");
1370
- this.releaseTemp(pOffTmp, "i32");
1371
- this.releaseTemp(pArrTmp, arrW);
1372
- }
1373
-
1374
- _emitBuilderWriteStringCore(bTmp, strTmp) {
1375
- const structInfo = this.mod.getStructType("strings.Builder");
1376
- const strGo = { kind: "basic", name: "string" };
1377
- const sliceInfo = this.mod.getSliceType(strGo);
1378
- const arrInfo = sliceInfo.arrInfo;
1379
- const sliceW = {
1380
- kind: "ref",
1381
- nullable: true,
1382
- typeIndex: sliceInfo.typeIndex,
1383
- };
1384
- const arrW = { kind: "ref", nullable: true, typeIndex: arrInfo.typeIndex };
1385
-
1386
- const lenTmp = this.acquireTemp("i32");
1387
- this.pushInstruction({ op: "local.get", index: strTmp });
1388
- this.pushInstruction({
1389
- op: "call",
1390
- funcIndex: this.mod.getStringLenImportIndex(),
1391
- });
1392
- this.pushInstruction({ op: "local.set", index: lenTmp });
1393
-
1394
- // copy check
1395
- this.pushInstruction({ op: "local.get", index: bTmp });
1396
- this.pushInstruction({
1397
- op: "struct.get",
1398
- typeIndex: structInfo.typeIndex,
1399
- fieldIndex: 2,
1400
- });
1401
- this.pushInstruction("ref.is_null");
1402
- this.pushInstruction({ op: "if", blockType: "void" });
1403
- this.pushInstruction({ op: "local.get", index: bTmp });
1404
- this.pushInstruction({ op: "local.get", index: bTmp });
1405
- this.pushInstruction({
1406
- op: "struct.set",
1407
- typeIndex: structInfo.typeIndex,
1408
- fieldIndex: 2,
1409
- });
1410
- this.pushInstruction("else");
1411
- this.pushInstruction({ op: "local.get", index: bTmp });
1412
- this.pushInstruction({
1413
- op: "struct.get",
1414
- typeIndex: structInfo.typeIndex,
1415
- fieldIndex: 2,
1416
- });
1417
- this.pushInstruction({ op: "ref.cast", heapType: "eq" });
1418
- this.pushInstruction({ op: "local.get", index: bTmp });
1419
- this.pushInstruction("ref.eq");
1420
- this.pushInstruction("i32.eqz");
1421
- this.pushInstruction({ op: "if", blockType: "void" });
1422
- this.emitPanic("strings: illegal use of non-zero Builder copied by value");
1423
- this.pushInstruction("end");
1424
- this.pushInstruction("end");
1425
-
1426
- // append string to b._buf
1427
- const oldSliceTmp = this.acquireTemp(sliceW);
1428
- this.pushInstruction({ op: "local.get", index: bTmp });
1429
- this.pushInstruction({
1430
- op: "struct.get",
1431
- typeIndex: structInfo.typeIndex,
1432
- fieldIndex: 0,
1433
- });
1434
- this.pushInstruction({ op: "local.set", index: oldSliceTmp });
1435
-
1436
- const oldArrTmp = this.acquireTemp(arrW);
1437
- const oldOffTmp = this.acquireTemp("i32");
1438
- const oldLenTmp = this.acquireTemp("i32");
1439
- const oldCapTmp = this.acquireTemp("i32");
1440
- this._emitSliceUnpack(oldSliceTmp, sliceInfo, {
1441
- arr: oldArrTmp,
1442
- off: oldOffTmp,
1443
- len: oldLenTmp,
1444
- cap: oldCapTmp,
1445
- });
1446
- this.releaseTemp(oldSliceTmp, sliceW);
1447
-
1448
- const newArrTmp = this.acquireTemp(arrW);
1449
- const newOffTmp = this.acquireTemp("i32");
1450
- const newCapTmp = this.acquireTemp("i32");
1451
- const newLenTmp = this.acquireTemp("i32");
1452
- this.pushInstruction({ op: "local.get", index: oldLenTmp });
1453
- this.pushInstruction({ op: "i32.const", value: 1 });
1454
- this.pushInstruction("i32.add");
1455
- this.pushInstruction({ op: "local.set", index: newLenTmp });
1456
-
1457
- this._emitGrowSlice({
1458
- arrInfo,
1459
- elemGoType: strGo,
1460
- oldArrTmp,
1461
- oldOffTmp,
1462
- oldLenTmp,
1463
- oldCapTmp,
1464
- newArrTmp,
1465
- newOffTmp,
1466
- newLenTmp,
1467
- newCapTmp,
1468
- });
1469
-
1470
- this.pushInstruction({ op: "local.get", index: newArrTmp });
1471
- this.pushInstruction({ op: "local.get", index: newOffTmp });
1472
- this.pushInstruction({ op: "local.get", index: oldLenTmp });
1473
- this.pushInstruction("i32.add");
1474
- this.pushInstruction({ op: "local.get", index: strTmp });
1475
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
1476
-
1477
- this.pushInstruction({ op: "local.get", index: bTmp });
1478
- this.pushInstruction({ op: "local.get", index: newArrTmp });
1479
- this.pushInstruction({ op: "local.get", index: newOffTmp });
1480
- this.pushInstruction({ op: "local.get", index: newLenTmp });
1481
- this.pushInstruction({ op: "local.get", index: newCapTmp });
1482
- this.pushInstruction({
1483
- op: "struct.new",
1484
- typeIndex: sliceInfo.typeIndex,
1485
- });
1486
- this.pushInstruction({
1487
- op: "struct.set",
1488
- typeIndex: structInfo.typeIndex,
1489
- fieldIndex: 0,
1490
- });
1491
-
1492
- this.pushInstruction({ op: "local.get", index: bTmp });
1493
- this.pushInstruction({ op: "local.get", index: bTmp });
1494
- this.pushInstruction({
1495
- op: "struct.get",
1496
- typeIndex: structInfo.typeIndex,
1497
- fieldIndex: 1,
1498
- });
1499
- this.pushInstruction({ op: "local.get", index: lenTmp });
1500
- this.pushInstruction("i64.extend_i32_u");
1501
- this.pushInstruction("i64.add");
1502
- this.pushInstruction({
1503
- op: "struct.set",
1504
- typeIndex: structInfo.typeIndex,
1505
- fieldIndex: 1,
1506
- });
1507
-
1508
- // return (len, nil)
1509
- this.pushInstruction({ op: "local.get", index: lenTmp });
1510
- this.pushInstruction("i64.extend_i32_u");
1511
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1512
-
1513
- this.releaseTemp(newLenTmp, "i32");
1514
- this.releaseTemp(newCapTmp, "i32");
1515
- this.releaseTemp(newOffTmp, "i32");
1516
- this.releaseTemp(newArrTmp, arrW);
1517
- this.releaseTemp(oldCapTmp, "i32");
1518
- this.releaseTemp(oldLenTmp, "i32");
1519
- this.releaseTemp(oldOffTmp, "i32");
1520
- this.releaseTemp(oldArrTmp, arrW);
1521
- this.releaseTemp(lenTmp, "i32");
1522
- }
1523
-
1524
- _emitHelperBufferWrite(_fn) {
1525
- this._emitBufferWriteCore(0, 1);
1526
- this.pushInstruction("return");
1527
- }
1528
-
1529
- _emitHelperBufferWriteString(_fn) {
1530
- this._emitBufferWriteStringCore(0, 1);
1531
- this.pushInstruction("return");
1532
- }
1533
-
1534
- _emitBufferWriteCore(bTmp, pTmp, structName = "bytes.Buffer") {
1535
- const structInfo = this.mod.getStructType(structName);
1536
- const byteGo = { kind: "basic", name: "byte" };
1537
- const sliceInfo = this.mod.getSliceType(byteGo);
1538
- const sliceW = {
1539
- kind: "ref",
1540
- nullable: true,
1541
- typeIndex: sliceInfo.typeIndex,
1542
- };
1543
- const arrW = {
1544
- kind: "ref",
1545
- nullable: true,
1546
- typeIndex: sliceInfo.arrInfo.typeIndex,
1547
- };
1548
-
1549
- const bufSliceTmp = this.acquireTemp(sliceW);
1550
- this.pushInstruction({ op: "local.get", index: bTmp });
1551
- this.pushInstruction({
1552
- op: "struct.get",
1553
- typeIndex: structInfo.typeIndex,
1554
- fieldIndex: 0,
1555
- });
1556
- this.pushInstruction({ op: "local.set", index: bufSliceTmp });
1557
- this.pushInstruction({ op: "local.get", index: bufSliceTmp });
1558
- this.pushInstruction("ref.is_null");
1559
- this.pushInstruction({ op: "if", blockType: "void" });
1560
- this.pushInstruction({
1561
- op: "global.get",
1562
- index: sliceInfo.emptyGlobalIndex,
1563
- });
1564
- this.pushInstruction({ op: "local.set", index: bufSliceTmp });
1565
- this.pushInstruction("end");
1566
-
1567
- const pArrTmp = this.acquireTemp(arrW);
1568
- const pOffTmp = this.acquireTemp("i32");
1569
- const pLenTmp = this.acquireTemp("i32");
1570
- const pCapTmp = this.acquireTemp("i32");
1571
- this._emitSliceUnpack(pTmp, sliceInfo, {
1572
- arr: pArrTmp,
1573
- off: pOffTmp,
1574
- len: pLenTmp,
1575
- cap: pCapTmp,
1576
- });
1577
- this.releaseTemp(pCapTmp, "i32");
1578
-
1579
- this._emitAppendSliceBytes(bufSliceTmp, pTmp, pLenTmp, sliceInfo, arrW);
1580
-
1581
- this.pushInstruction({ op: "local.get", index: bTmp });
1582
- this.pushInstruction({ op: "local.get", index: bufSliceTmp });
1583
- this.pushInstruction({
1584
- op: "struct.set",
1585
- typeIndex: structInfo.typeIndex,
1586
- fieldIndex: 0,
1587
- });
1588
-
1589
- this.pushInstruction({ op: "local.get", index: pLenTmp });
1590
- this.pushInstruction("i64.extend_i32_u");
1591
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1592
-
1593
- this.releaseTemp(bufSliceTmp, sliceW);
1594
- this.releaseTemp(pLenTmp, "i32");
1595
- this.releaseTemp(pOffTmp, "i32");
1596
- this.releaseTemp(pArrTmp, arrW);
1597
- }
1598
-
1599
- _emitBufferWriteStringCore(bTmp, strTmp) {
1600
- const sliceW = {
1601
- kind: "ref",
1602
- nullable: true,
1603
- typeIndex: this.mod.getSliceType({ kind: "basic", name: "byte" })
1604
- .typeIndex,
1605
- };
1606
- const pTmp = this.acquireTemp(sliceW);
1607
- this.pushInstruction({ op: "local.get", index: strTmp });
1608
- this._emitStringToByteSlice({ elem: { kind: "basic", name: "byte" } });
1609
- this.pushInstruction({ op: "local.set", index: pTmp });
1610
-
1611
- this._emitBufferWriteCore(bTmp, pTmp);
1612
- this.releaseTemp(pTmp, sliceW);
1613
- }
1614
-
1615
- _emitHelperBufferRead(_fn) {
1616
- this._emitBufferReadCore(0, 1);
1617
- this.pushInstruction("return");
1618
- }
1619
-
1620
- _emitBufferReadCore(bTmp, pTmp) {
1621
- const structInfo = this.mod.getStructType("bytes.Buffer");
1622
- const byteElemGo = { kind: "basic", name: "byte" };
1623
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1624
- const arrW = {
1625
- kind: "ref",
1626
- nullable: true,
1627
- typeIndex: sliceInfo.arrInfo.typeIndex,
1628
- };
1629
- const sliceW = {
1630
- kind: "ref",
1631
- nullable: true,
1632
- typeIndex: sliceInfo.typeIndex,
1633
- };
1634
-
1635
- const pArrTmp = this.acquireTemp(arrW);
1636
- const pOffTmp = this.acquireTemp("i32");
1637
- const pLenTmp = this.acquireTemp("i32");
1638
- const pCapTmp = this.acquireTemp("i32");
1639
- this._emitSliceUnpack(pTmp, sliceInfo, {
1640
- arr: pArrTmp,
1641
- off: pOffTmp,
1642
- len: pLenTmp,
1643
- cap: pCapTmp,
1644
- });
1645
- this.releaseTemp(pCapTmp, "i32");
1646
-
1647
- const resNTmp = this.acquireTemp("i64");
1648
- const resErrTmp = this.acquireTemp("anyref");
1649
-
1650
- // Get b.buf (field 0)
1651
- const bufSliceTmp = this.acquireTemp(sliceW);
1652
- this.pushInstruction({ op: "local.get", index: bTmp });
1653
- this.pushInstruction({
1654
- op: "struct.get",
1655
- typeIndex: structInfo.typeIndex,
1656
- fieldIndex: 0,
1657
- });
1658
- this.pushInstruction({ op: "local.set", index: bufSliceTmp });
1659
-
1660
- this.pushInstruction({ op: "local.get", index: bufSliceTmp });
1661
- this.pushInstruction("ref.is_null");
1662
- this.pushInstruction({ op: "if", blockType: "void" });
1663
- this.pushInstruction({
1664
- op: "global.get",
1665
- index: sliceInfo.emptyGlobalIndex,
1666
- });
1667
- this.pushInstruction({ op: "local.set", index: bufSliceTmp });
1668
- this.pushInstruction("end");
1669
-
1670
- const srcArrTmp = this.acquireTemp(arrW);
1671
- const srcOffTmp = this.acquireTemp("i32");
1672
- const srcLenTmp = this.acquireTemp("i32");
1673
- const srcCapTmp = this.acquireTemp("i32");
1674
- this._emitSliceUnpack(bufSliceTmp, sliceInfo, {
1675
- arr: srcArrTmp,
1676
- off: srcOffTmp,
1677
- len: srcLenTmp,
1678
- cap: srcCapTmp,
1679
- });
1680
- this.releaseTemp(bufSliceTmp, sliceW);
1681
-
1682
- // if srcLen == 0:
1683
- // if pLen == 0: (0, nil) else: (0, io.EOF)
1684
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
1685
- this.pushInstruction("i32.eqz");
1686
- this.pushInstruction({ op: "if", blockType: "void" });
1687
- this.pushInstruction({ op: "i64.const", value: 0n });
1688
- this.pushInstruction({ op: "local.set", index: resNTmp });
1689
- this.pushInstruction({ op: "local.get", index: pLenTmp });
1690
- this.pushInstruction("i32.eqz");
1691
- this.pushInstruction({ op: "if", blockType: "anyref" });
1692
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1693
- this.pushInstruction("else");
1694
- this.emitIoConst("EOF", "anyref");
1695
- this.pushInstruction("end");
1696
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1697
- this.pushInstruction("else");
1698
-
1699
- // n = min(p.len, srcLen)
1700
- const nTmp = this.acquireTemp("i32");
1701
- this.pushInstruction({ op: "local.get", index: pLenTmp });
1702
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
1703
- this.pushInstruction("i32.lt_s");
1704
- this.pushInstruction({ op: "if", blockType: "i32" });
1705
- this.pushInstruction({ op: "local.get", index: pLenTmp });
1706
- this.pushInstruction("else");
1707
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
1708
- this.pushInstruction("end");
1709
- this.pushInstruction({ op: "local.set", index: nTmp });
1710
-
1711
- // copy: pArr[pOff .. pOff + n] = srcArr[srcOff .. srcOff + n]
1712
- this.pushInstruction({ op: "local.get", index: pArrTmp });
1713
- this.pushInstruction({ op: "local.get", index: pOffTmp });
1714
- this.pushInstruction({ op: "local.get", index: srcArrTmp });
1715
- this.pushInstruction({ op: "local.get", index: srcOffTmp });
1716
- this.pushInstruction({ op: "local.get", index: nTmp });
1717
- this._emitArrayCopy(sliceInfo.arrInfo, byteElemGo);
1718
-
1719
- // update b.buf: struct.new sliceInfo (srcArr, srcOff + n, srcLen - n, srcCap - n)
1720
- this.pushInstruction({ op: "local.get", index: bTmp });
1721
- this.pushInstruction({ op: "local.get", index: srcArrTmp });
1722
- this.pushInstruction({ op: "local.get", index: srcOffTmp });
1723
- this.pushInstruction({ op: "local.get", index: nTmp });
1724
- this.pushInstruction("i32.add");
1725
- this.pushInstruction({ op: "local.get", index: srcLenTmp });
1726
- this.pushInstruction({ op: "local.get", index: nTmp });
1727
- this.pushInstruction("i32.sub");
1728
- this.pushInstruction({ op: "local.get", index: srcCapTmp });
1729
- this.pushInstruction({ op: "local.get", index: nTmp });
1730
- this.pushInstruction("i32.sub");
1731
- this.pushInstruction({
1732
- op: "struct.new",
1733
- typeIndex: sliceInfo.typeIndex,
1734
- });
1735
- this.pushInstruction({
1736
- op: "struct.set",
1737
- typeIndex: structInfo.typeIndex,
1738
- fieldIndex: 0,
1739
- });
1740
-
1741
- this.pushInstruction({ op: "local.get", index: nTmp });
1742
- this.pushInstruction("i64.extend_i32_u");
1743
- this.pushInstruction({ op: "local.set", index: resNTmp });
1744
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1745
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1746
-
1747
- this.releaseTemp(nTmp, "i32");
1748
- this.pushInstruction("end"); // end else
1749
-
1750
- this.releaseTemp(srcCapTmp, "i32");
1751
- this.releaseTemp(srcLenTmp, "i32");
1752
- this.releaseTemp(srcOffTmp, "i32");
1753
- this.releaseTemp(srcArrTmp, arrW);
1754
-
1755
- this.pushInstruction({ op: "local.get", index: resNTmp });
1756
- this.pushInstruction({ op: "local.get", index: resErrTmp });
1757
-
1758
- this.releaseTemp(resErrTmp, "anyref");
1759
- this.releaseTemp(resNTmp, "i64");
1760
- this.releaseTemp(pLenTmp, "i32");
1761
- this.releaseTemp(pOffTmp, "i32");
1762
- this.releaseTemp(pArrTmp, arrW);
1763
- }
1764
-
1765
- _emitHelperStringsReaderRead(_fn) {
1766
- this._emitStringsReaderReadCore(0, 1);
1767
- this.pushInstruction("return");
1768
- }
1769
-
1770
- _emitHelperStringsReaderLen(_fn) {
1771
- this._emitStringsReaderLenCore(0, "i64");
1772
- this.pushInstruction("return");
1773
- }
1774
-
1775
- _emitHelperStringsReaderReset(_fn) {
1776
- this._emitStringsReaderResetCore(0, 1);
1777
- this.pushInstruction("return");
1778
- }
1779
-
1780
- _emitHelperBytesReaderRead(_fn) {
1781
- this._emitBytesReaderReadCore(0, 1);
1782
- this.pushInstruction("return");
1783
- }
1784
-
1785
- _emitHelperBytesReaderLen(_fn) {
1786
- this._emitBytesReaderLenCore(0, "i64");
1787
- this.pushInstruction("return");
1788
- }
1789
-
1790
- _emitHelperBytesReaderReset(_fn) {
1791
- this._emitBytesReaderResetCore(0, 1);
1792
- this.pushInstruction("return");
1793
- }
1794
-
1795
- _emitHelperDiscardWrite(_fn) {
1796
- const byteElemGo = { kind: "basic", name: "byte" };
1797
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1798
- this.pushInstruction({ op: "local.get", index: 1 });
1799
- this.pushInstruction({
1800
- op: "struct.get",
1801
- typeIndex: sliceInfo.typeIndex,
1802
- fieldIndex: 2,
1803
- });
1804
- this.pushInstruction("i64.extend_i32_u");
1805
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1806
- this.pushInstruction("return");
1807
- }
1808
-
1809
- _emitHelperDiscardWriteString(_fn) {
1810
- this.pushInstruction({ op: "local.get", index: 1 });
1811
- this.pushInstruction({
1812
- op: "call",
1813
- funcIndex: this.mod.getStringLenImportIndex(),
1814
- });
1815
- this.pushInstruction("i64.extend_i32_u");
1816
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1817
- this.pushInstruction("return");
1818
- }
1819
-
1820
- _emitHelperLimitedReaderRead(_fn) {
1821
- this._emitLimitedReaderReadCore(0, 1);
1822
- this.pushInstruction("return");
1823
- }
1824
-
1825
- _emitLimitedReaderReadCore(lTmp, pTmp) {
1826
- const structInfo = this.mod.getStructType("io.LimitedReader");
1827
- const byteElemGo = { kind: "basic", name: "byte" };
1828
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1829
- const arrW = {
1830
- kind: "ref",
1831
- nullable: true,
1832
- typeIndex: sliceInfo.arrInfo.typeIndex,
1833
- };
1834
-
1835
- // 1. Check if l.N <= 0
1836
- this.pushInstruction({ op: "local.get", index: lTmp });
1837
- this.pushInstruction({
1838
- op: "struct.get",
1839
- typeIndex: structInfo.typeIndex,
1840
- fieldIndex: 1, // N
1841
- });
1842
- this.pushInstruction({ op: "i64.const", value: 0n });
1843
- this.pushInstruction("i64.le_s");
1844
- this.pushInstruction({ op: "if", blockType: "void" });
1845
- this.pushInstruction({ op: "i64.const", value: 0n });
1846
- this.emitIoConst("EOF", "anyref");
1847
- this.pushInstruction("return");
1848
- this.pushInstruction("end");
1849
-
1850
- // 2. If int64(len(p)) > l.N, subslice p = p[0:l.N]
1851
- const pArrTmp = this.acquireTemp(arrW);
1852
- const pOffTmp = this.acquireTemp("i32");
1853
- const pLenTmp = this.acquireTemp("i32");
1854
- const pCapTmp = this.acquireTemp("i32");
1855
- this._emitSliceUnpack(pTmp, sliceInfo, {
1856
- arr: pArrTmp,
1857
- off: pOffTmp,
1858
- len: pLenTmp,
1859
- cap: pCapTmp,
1860
- });
1861
-
1862
- this.pushInstruction({ op: "local.get", index: pLenTmp });
1863
- this.pushInstruction("i64.extend_i32_u");
1864
- this.pushInstruction({ op: "local.get", index: lTmp });
1865
- this.pushInstruction({
1866
- op: "struct.get",
1867
- typeIndex: structInfo.typeIndex,
1868
- fieldIndex: 1, // N
1869
- });
1870
- this.pushInstruction("i64.gt_s");
1871
- this.pushInstruction({ op: "if", blockType: "void" });
1872
- this.pushInstruction({ op: "local.get", index: lTmp });
1873
- this.pushInstruction({
1874
- op: "struct.get",
1875
- typeIndex: structInfo.typeIndex,
1876
- fieldIndex: 1,
1877
- });
1878
- this.pushInstruction("i32.wrap_i64");
1879
- this.pushInstruction({ op: "local.set", index: pLenTmp });
1880
- this.pushInstruction({ op: "local.get", index: pArrTmp });
1881
- this.pushInstruction({ op: "local.get", index: pOffTmp });
1882
- this.pushInstruction({ op: "local.get", index: pLenTmp });
1883
- this.pushInstruction({ op: "local.get", index: pCapTmp });
1884
- this.pushInstruction({
1885
- op: "struct.new",
1886
- typeIndex: sliceInfo.typeIndex,
1887
- });
1888
- this.pushInstruction({ op: "local.set", index: pTmp });
1889
- this.pushInstruction("end");
1890
-
1891
- this.releaseTemp(pCapTmp, "i32");
1892
- this.releaseTemp(pLenTmp, "i32");
1893
- this.releaseTemp(pOffTmp, "i32");
1894
- this.releaseTemp(pArrTmp, arrW);
1895
-
1896
- // 3. Call l.R.Read(p)
1897
- this.pushInstruction({ op: "local.get", index: lTmp });
1898
- this.pushInstruction({
1899
- op: "struct.get",
1900
- typeIndex: structInfo.typeIndex,
1901
- fieldIndex: 0, // R
1902
- });
1903
- this.pushInstruction({ op: "local.get", index: pTmp });
1904
-
1905
- const dispatchIdx = this.mod.resolveFuncIndex("__dispatch_io.Reader_Read");
1906
- if (dispatchIdx !== null) {
1907
- this.pushInstruction({ op: "call", funcIndex: dispatchIdx });
1908
- } else {
1909
- this.pushInstruction({ op: "i64.const", value: 0n });
1910
- this.pushInstruction({ op: "ref.null", heapType: "any" });
1911
- }
1912
-
1913
- const resErrTmp = this.acquireTemp("anyref");
1914
- const resNTmp = this.acquireTemp("i64");
1915
- this.pushInstruction({ op: "local.set", index: resErrTmp });
1916
- this.pushInstruction({ op: "local.set", index: resNTmp });
1917
-
1918
- // 4. Update l.N -= n:
1919
- this.pushInstruction({ op: "local.get", index: lTmp });
1920
- this.pushInstruction({ op: "local.get", index: lTmp });
1921
- this.pushInstruction({
1922
- op: "struct.get",
1923
- typeIndex: structInfo.typeIndex,
1924
- fieldIndex: 1, // N
1925
- });
1926
- this.pushInstruction({ op: "local.get", index: resNTmp });
1927
- this.pushInstruction("i64.sub");
1928
- this.pushInstruction({
1929
- op: "struct.set",
1930
- typeIndex: structInfo.typeIndex,
1931
- fieldIndex: 1, // N
1932
- });
1933
-
1934
- // 5. Return (n, err)
1935
- this.pushInstruction({ op: "local.get", index: resNTmp });
1936
- this.pushInstruction({ op: "local.get", index: resErrTmp });
1937
- this.releaseTemp(resNTmp, "i64");
1938
- this.releaseTemp(resErrTmp, "anyref");
1939
- }
1940
-
1941
- emitIoLimitedReaderMethodCall(method, recvExpr, args, _targetWasmType) {
1942
- if (method === "Read") {
1943
- const structInfo = this.mod.getStructType("io.LimitedReader");
1944
- const lrW = {
1945
- kind: "ref",
1946
- nullable: true,
1947
- typeIndex: structInfo.typeIndex,
1948
- };
1949
- const lTmp = this.acquireTemp(lrW);
1950
- this.emitExpr(recvExpr, lrW);
1951
- this.pushInstruction({ op: "local.set", index: lTmp });
1952
-
1953
- const byteElemGo = { kind: "basic", name: "byte" };
1954
- const sliceInfo = this.mod.getSliceType(byteElemGo);
1955
- const sliceW = {
1956
- kind: "ref",
1957
- nullable: true,
1958
- typeIndex: sliceInfo.typeIndex,
1959
- };
1960
- const pTmp = this.acquireTemp(sliceW);
1961
- this.emitExpr(args[0], sliceW);
1962
- this.pushInstruction({ op: "local.set", index: pTmp });
1963
-
1964
- this._emitLimitedReaderReadCore(lTmp, pTmp);
1965
- this.releaseTemp(pTmp, sliceW);
1966
- this.releaseTemp(lTmp, lrW);
1967
- return;
1968
- }
1969
- throw new Error(`Unsupported io.LimitedReader method: ${method}`);
1970
- }
1971
-
1972
- _emitHelperSha256Write(_fn) {
1973
- this._emitBufferWriteCore(0, 1, "sha256.digest");
1974
- this.pushInstruction("return");
1975
- }
1976
-
1977
- _emitHelperSha256Reset(_fn) {
1978
- const structInfo = this.mod.getStructType("sha256.digest");
1979
- const byteGo = { kind: "basic", name: "byte" };
1980
- const sliceInfo = this.mod.getSliceType(byteGo);
1981
- this.pushInstruction({ op: "local.get", index: 0 });
1982
- this.pushInstruction({
1983
- op: "global.get",
1984
- index: sliceInfo.emptyGlobalIndex,
1985
- });
1986
- this.pushInstruction({
1987
- op: "struct.set",
1988
- typeIndex: structInfo.typeIndex,
1989
- fieldIndex: 0,
1990
- });
1991
- this.pushInstruction("return");
1992
- }
1993
-
1994
- _emitHelperSha256Size(_fn) {
1995
- this.pushInstruction({ op: "i64.const", value: 32n });
1996
- this.pushInstruction("return");
1997
- }
1998
-
1999
- _emitHelperSha256BlockSize(_fn) {
2000
- this.pushInstruction({ op: "i64.const", value: 64n });
2001
- this.pushInstruction("return");
2002
- }
2003
-
2004
- _emitHelperSha256Sum(_fn) {
2005
- const structInfo = this.mod.getStructType("sha256.digest");
2006
- const byteGo = { kind: "basic", name: "byte" };
2007
- const sliceInfo = this.mod.getSliceType(byteGo);
2008
- const arrInfo = sliceInfo.arrInfo;
2009
- const sliceW = {
2010
- kind: "ref",
2011
- nullable: true,
2012
- typeIndex: sliceInfo.typeIndex,
2013
- };
2014
- const arrW = { kind: "ref", nullable: true, typeIndex: arrInfo.typeIndex };
2015
-
2016
- const bufSliceTmp = this.acquireTemp(sliceW);
2017
- this.pushInstruction({ op: "local.get", index: 0 });
2018
- this.pushInstruction({
2019
- op: "struct.get",
2020
- typeIndex: structInfo.typeIndex,
2021
- fieldIndex: 0,
2022
- });
2023
- this.pushInstruction({ op: "local.set", index: bufSliceTmp });
2024
-
2025
- this.pushInstruction({ op: "local.get", index: bufSliceTmp });
2026
- this.pushInstruction("ref.is_null");
2027
- this.pushInstruction({ op: "if", blockType: "void" });
2028
- this.pushInstruction({
2029
- op: "global.get",
2030
- index: sliceInfo.emptyGlobalIndex,
2031
- });
2032
- this.pushInstruction({ op: "local.set", index: bufSliceTmp });
2033
- this.pushInstruction("end");
2034
-
2035
- const dArrTmp = this.acquireTemp(arrW);
2036
- const dOffTmp = this.acquireTemp("i32");
2037
- const dLenTmp = this.acquireTemp("i32");
2038
- const dCapTmp = this.acquireTemp("i32");
2039
- this._emitSliceUnpack(bufSliceTmp, sliceInfo, {
2040
- arr: dArrTmp,
2041
- off: dOffTmp,
2042
- len: dLenTmp,
2043
- cap: dCapTmp,
2044
- });
2045
- this.releaseTemp(dCapTmp, "i32");
2046
-
2047
- this.pushInstruction({ op: "local.get", index: dLenTmp });
2048
- this._callStdlib("raw_bytes_init");
2049
-
2050
- const iLoc = this.acquireTemp("i32");
2051
- this.pushInstruction({ op: "i32.const", value: 0 });
2052
- this.pushInstruction({ op: "local.set", index: iLoc });
2053
-
2054
- this.pushInstruction({ op: "block", blockType: "void" });
2055
- this.pushInstruction({ op: "loop", blockType: "void" });
2056
- this.pushInstruction({ op: "local.get", index: iLoc });
2057
- this.pushInstruction({ op: "local.get", index: dLenTmp });
2058
- this.pushInstruction("i32.ge_s");
2059
- this.pushInstruction({ op: "br_if", depth: 1 });
2060
-
2061
- this.pushInstruction({ op: "local.get", index: dArrTmp });
2062
- this.pushInstruction({ op: "local.get", index: dOffTmp });
2063
- this.pushInstruction({ op: "local.get", index: iLoc });
2064
- this.pushInstruction("i32.add");
2065
- this.pushInstruction({ op: "array.get", typeIndex: arrInfo.typeIndex });
2066
- this._callStdlib("raw_bytes_push");
2067
-
2068
- this.pushInstruction({ op: "local.get", index: iLoc });
2069
- this.pushInstruction({ op: "i32.const", value: 1 });
2070
- this.pushInstruction("i32.add");
2071
- this.pushInstruction({ op: "local.set", index: iLoc });
2072
- this.pushInstruction({ op: "br", depth: 0 });
2073
- this.pushInstruction("end");
2074
- this.pushInstruction("end");
2075
-
2076
- this._callStdlib("crypto_sha256_sum");
2077
- this.pushInstruction("drop");
2078
-
2079
- const outArrTmp = this.acquireTemp(arrW);
2080
- this.pushInstruction({ op: "i32.const", value: 32 });
2081
- this.pushInstruction({
2082
- op: "array.new_default",
2083
- typeIndex: arrInfo.typeIndex,
2084
- });
2085
- this.pushInstruction({ op: "local.set", index: outArrTmp });
2086
-
2087
- this.pushInstruction({ op: "i32.const", value: 0 });
2088
- this.pushInstruction({ op: "local.set", index: iLoc });
2089
-
2090
- this.pushInstruction({ op: "block", blockType: "void" });
2091
- this.pushInstruction({ op: "loop", blockType: "void" });
2092
- this.pushInstruction({ op: "local.get", index: iLoc });
2093
- this.pushInstruction({ op: "i32.const", value: 32 });
2094
- this.pushInstruction("i32.ge_s");
2095
- this.pushInstruction({ op: "br_if", depth: 1 });
2096
-
2097
- this.pushInstruction({ op: "local.get", index: outArrTmp });
2098
- this.pushInstruction({ op: "local.get", index: iLoc });
2099
- this.pushInstruction({ op: "local.get", index: iLoc });
2100
- this._callStdlib("raw_bytes_get");
2101
- this.pushInstruction({ op: "array.set", typeIndex: arrInfo.typeIndex });
2102
-
2103
- this.pushInstruction({ op: "local.get", index: iLoc });
2104
- this.pushInstruction({ op: "i32.const", value: 1 });
2105
- this.pushInstruction("i32.add");
2106
- this.pushInstruction({ op: "local.set", index: iLoc });
2107
- this.pushInstruction({ op: "br", depth: 0 });
2108
- this.pushInstruction("end");
2109
- this.pushInstruction("end");
2110
-
2111
- const outSliceTmp = this.acquireTemp(sliceW);
2112
- this.pushInstruction({ op: "local.get", index: outArrTmp });
2113
- this.pushInstruction({ op: "i32.const", value: 0 });
2114
- this.pushInstruction({ op: "i32.const", value: 32 });
2115
- this.pushInstruction({ op: "i32.const", value: 32 });
2116
- this.pushInstruction({
2117
- op: "struct.new",
2118
- typeIndex: sliceInfo.typeIndex,
2119
- });
2120
- this.pushInstruction({ op: "local.set", index: outSliceTmp });
2121
-
2122
- this.pushInstruction({ op: "local.get", index: 1 });
2123
- this.pushInstruction("ref.is_null");
2124
- this.pushInstruction({ op: "if", blockType: "void" });
2125
- this.pushInstruction({ op: "local.get", index: outSliceTmp });
2126
- this.pushInstruction("return");
2127
- this.pushInstruction("end");
2128
-
2129
- this.pushInstruction({ op: "local.get", index: 1 });
2130
- this.pushInstruction({
2131
- op: "struct.get",
2132
- typeIndex: sliceInfo.typeIndex,
2133
- fieldIndex: 1,
2134
- });
2135
- this.pushInstruction("i32.eqz");
2136
- this.pushInstruction({ op: "if", blockType: "void" });
2137
- this.pushInstruction({ op: "local.get", index: outSliceTmp });
2138
- this.pushInstruction("return");
2139
- this.pushInstruction("end");
2140
-
2141
- const countTmp = this.acquireTemp("i32");
2142
- this.pushInstruction({ op: "i32.const", value: 32 });
2143
- this.pushInstruction({ op: "local.set", index: countTmp });
2144
- const bTmp = this.acquireTemp(sliceW);
2145
- this.pushInstruction({ op: "local.get", index: 1 });
2146
- this.pushInstruction({ op: "local.set", index: bTmp });
2147
- this._emitAppendSliceBytes(bTmp, outSliceTmp, countTmp, sliceInfo, arrW);
2148
- this.pushInstruction({ op: "local.get", index: bTmp });
2149
- this.pushInstruction("return");
2150
-
2151
- this.releaseTemp(bTmp, sliceW);
2152
- this.releaseTemp(countTmp, "i32");
2153
- this.releaseTemp(outSliceTmp, sliceW);
2154
- this.releaseTemp(outArrTmp, arrW);
2155
- this.releaseTemp(iLoc, "i32");
2156
- this.releaseTemp(dLenTmp, "i32");
2157
- this.releaseTemp(dOffTmp, "i32");
2158
- this.releaseTemp(dArrTmp, arrW);
2159
- this.releaseTemp(bufSliceTmp, sliceW);
2160
- }
2161
- }