@scriptc/compiler 0.3.5 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +960 -82
- package/ambient/scriptc.d.ts +134 -0
- package/dist/backend/cycle-analysis.d.ts +1 -1
- package/dist/backend/cycle-analysis.js +1 -0
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-analysis.test.js +13 -1
- package/dist/backend/cycle-analysis.test.js.map +1 -1
- package/dist/backend/cycle-mutability.js +16 -5
- package/dist/backend/cycle-mutability.js.map +1 -1
- package/dist/backend/executable-features.js +13 -0
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/immutability.test.js +1 -1
- package/dist/backend/library-pack.js +6 -0
- package/dist/backend/library-pack.js.map +1 -1
- package/dist/backend/llvm/alloc.d.ts +41 -4
- package/dist/backend/llvm/alloc.js +138 -7
- package/dist/backend/llvm/alloc.js.map +1 -1
- package/dist/backend/llvm/alloc.test.js +30 -1
- package/dist/backend/llvm/alloc.test.js.map +1 -1
- package/dist/backend/llvm/appended-array-literals.test.js +1 -1
- package/dist/backend/llvm/array-search.test.js +1 -1
- package/dist/backend/llvm/blocks.d.ts +8 -0
- package/dist/backend/llvm/blocks.js +43 -1
- package/dist/backend/llvm/blocks.js.map +1 -1
- package/dist/backend/llvm/blocks.test.js +22 -1
- package/dist/backend/llvm/blocks.test.js.map +1 -1
- package/dist/backend/llvm/byte-numbers.js +15 -5
- package/dist/backend/llvm/byte-numbers.js.map +1 -1
- package/dist/backend/llvm/bytes-alias.d.ts +14 -0
- package/dist/backend/llvm/bytes-alias.js +20 -0
- package/dist/backend/llvm/bytes-alias.js.map +1 -0
- package/dist/backend/llvm/bytes-loop-versions.d.ts +86 -0
- package/dist/backend/llvm/bytes-loop-versions.js +506 -0
- package/dist/backend/llvm/bytes-loop-versions.js.map +1 -0
- package/dist/backend/llvm/bytes-loop-versions.test.d.ts +1 -0
- package/dist/backend/llvm/bytes-loop-versions.test.js +244 -0
- package/dist/backend/llvm/bytes-loop-versions.test.js.map +1 -0
- package/dist/backend/llvm/call-lifetimes.js +50 -1
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +34 -0
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/checked-narrows.test.js +1 -1
- package/dist/backend/llvm/checked-value-lifetimes.js +4 -1
- package/dist/backend/llvm/checked-value-lifetimes.js.map +1 -1
- package/dist/backend/llvm/classes.d.ts +11 -0
- package/dist/backend/llvm/classes.js +71 -14
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +58 -8
- package/dist/backend/llvm/classes.test.js.map +1 -1
- package/dist/backend/llvm/common.js +1 -0
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.d.ts +5 -1
- package/dist/backend/llvm/constant-callbacks.js +55 -12
- package/dist/backend/llvm/constant-callbacks.js.map +1 -1
- package/dist/backend/llvm/constant-callbacks.test.js +88 -1
- package/dist/backend/llvm/constant-callbacks.test.js.map +1 -1
- package/dist/backend/llvm/counted-loops.d.ts +4 -0
- package/dist/backend/llvm/counted-loops.js +37 -0
- package/dist/backend/llvm/counted-loops.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.d.ts +12 -3
- package/dist/backend/llvm/dense-array-access.js +72 -14
- package/dist/backend/llvm/dense-array-access.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.test.js +59 -3
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
- package/dist/backend/llvm/dense-array-loops.d.ts +51 -0
- package/dist/backend/llvm/dense-array-loops.js +162 -0
- package/dist/backend/llvm/dense-array-loops.js.map +1 -0
- package/dist/backend/llvm/dense-array-loops.test.d.ts +1 -0
- package/dist/backend/llvm/dense-array-loops.test.js +128 -0
- package/dist/backend/llvm/dense-array-loops.test.js.map +1 -0
- package/dist/backend/llvm/dyn-handle-tags.test.d.ts +1 -0
- package/dist/backend/llvm/dyn-handle-tags.test.js +38 -0
- package/dist/backend/llvm/dyn-handle-tags.test.js.map +1 -0
- package/dist/backend/llvm/dyn.d.ts +28 -4
- package/dist/backend/llvm/dyn.js +324 -179
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emit-function.d.ts +64 -0
- package/dist/backend/llvm/emit-function.js +1190 -0
- package/dist/backend/llvm/emit-function.js.map +1 -0
- package/dist/backend/llvm/emit-module.d.ts +24 -0
- package/dist/backend/llvm/emit-module.js +1535 -0
- package/dist/backend/llvm/emit-module.js.map +1 -0
- package/dist/backend/llvm/emit-statements.d.ts +58 -0
- package/dist/backend/llvm/emit-statements.js +1964 -0
- package/dist/backend/llvm/emit-statements.js.map +1 -0
- package/dist/backend/llvm/emitter.d.ts +576 -268
- package/dist/backend/llvm/emitter.js +801 -4447
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +57 -3
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +73 -46
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-async.test.js +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +2 -0
- package/dist/backend/llvm/expr-bytes.js +76 -29
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.d.ts +6 -2
- package/dist/backend/llvm/expr-callbacks.js +48 -11
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.d.ts +1 -1
- package/dist/backend/llvm/expr-calls.js +71 -53
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-calls.test.js +1 -1
- package/dist/backend/llvm/expr-containers.js +39 -15
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-control.js +16 -16
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dispatch.js +1 -0
- package/dist/backend/llvm/expr-dispatch.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.d.ts +3 -0
- package/dist/backend/llvm/expr-dynamic.js +92 -63
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +1 -1
- package/dist/backend/llvm/expr-primitives.js +132 -25
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.test.js +2 -2
- package/dist/backend/llvm/expr-records.d.ts +1 -1
- package/dist/backend/llvm/expr-records.js +32 -11
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +54 -12
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.js +2 -2
- package/dist/backend/llvm/expr-stream-callbacks.js +22 -1
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/int32-abi.test.js +2 -2
- package/dist/backend/llvm/integer-clones.test.js +3 -3
- package/dist/backend/llvm/integer-remainder.d.ts +34 -13
- package/dist/backend/llvm/integer-remainder.js +156 -22
- package/dist/backend/llvm/integer-remainder.js.map +1 -1
- package/dist/backend/llvm/intern-tables.test.js +1 -1
- package/dist/backend/llvm/jsval-encoding.d.ts +21 -0
- package/dist/backend/llvm/jsval-encoding.js +20 -0
- package/dist/backend/llvm/jsval-encoding.js.map +1 -0
- package/dist/backend/llvm/jsval.d.ts +12 -0
- package/dist/backend/llvm/jsval.js +488 -0
- package/dist/backend/llvm/jsval.js.map +1 -0
- package/dist/backend/llvm/lazy-captures.d.ts +12 -2
- package/dist/backend/llvm/lazy-captures.js +39 -17
- package/dist/backend/llvm/lazy-captures.js.map +1 -1
- package/dist/backend/llvm/lib-abi.js +1 -1
- package/dist/backend/llvm/lib-abi.js.map +1 -1
- package/dist/backend/llvm/lib-connect.js +1 -1
- package/dist/backend/llvm/lib-connect.js.map +1 -1
- package/dist/backend/llvm/lib-datagram.js +14 -8
- package/dist/backend/llvm/lib-datagram.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +217 -24
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +102 -13
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-http2.js +3 -3
- package/dist/backend/llvm/lib-http2.js.map +1 -1
- package/dist/backend/llvm/lib-lookup.js +2 -2
- package/dist/backend/llvm/lib-lookup.js.map +1 -1
- package/dist/backend/llvm/lib-network.js +77 -25
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +100 -50
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.d.ts +12 -0
- package/dist/backend/llvm/lib-shared.js +229 -5
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +46 -16
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-test.js +57 -8
- package/dist/backend/llvm/lib-test.js.map +1 -1
- package/dist/backend/llvm/lib-tls.js +4 -9
- package/dist/backend/llvm/lib-tls.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +2 -2
- package/dist/backend/llvm/local-array-reads.test.js +1 -1
- package/dist/backend/llvm/local-extents.d.ts +19 -0
- package/dist/backend/llvm/local-extents.js +169 -0
- package/dist/backend/llvm/local-extents.js.map +1 -0
- package/dist/backend/llvm/local-extents.test.d.ts +1 -0
- package/dist/backend/llvm/local-extents.test.js +92 -0
- package/dist/backend/llvm/local-extents.test.js.map +1 -0
- package/dist/backend/llvm/local-union-storage.js +7 -7
- package/dist/backend/llvm/local-union-storage.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.test.js +2 -2
- package/dist/backend/llvm/map-entry-fusion.test.js +1 -1
- package/dist/backend/llvm/map-number-lookup.js +2 -2
- package/dist/backend/llvm/map-number-lookup.test.js +2 -2
- package/dist/backend/llvm/map-read-lifetimes.test.js +2 -2
- package/dist/backend/llvm/narrow-guards.d.ts +38 -0
- package/dist/backend/llvm/narrow-guards.js +151 -0
- package/dist/backend/llvm/narrow-guards.js.map +1 -0
- package/dist/backend/llvm/nullable-unions.d.ts +70 -9
- package/dist/backend/llvm/nullable-unions.js +105 -6
- package/dist/backend/llvm/nullable-unions.js.map +1 -1
- package/dist/backend/llvm/nullable-unions.test.d.ts +1 -0
- package/dist/backend/llvm/nullable-unions.test.js +65 -0
- package/dist/backend/llvm/nullable-unions.test.js.map +1 -0
- package/dist/backend/llvm/publish.d.ts +4 -0
- package/dist/backend/llvm/publish.js +14 -2
- package/dist/backend/llvm/publish.js.map +1 -1
- package/dist/backend/llvm/publish.test.js +1 -1
- package/dist/backend/llvm/receivers.d.ts +31 -0
- package/dist/backend/llvm/receivers.js +395 -0
- package/dist/backend/llvm/receivers.js.map +1 -0
- package/dist/backend/llvm/record-results.d.ts +13 -2
- package/dist/backend/llvm/record-results.js +66 -6
- package/dist/backend/llvm/record-results.js.map +1 -1
- package/dist/backend/llvm/reference-effects.js +9 -0
- package/dist/backend/llvm/reference-effects.js.map +1 -1
- package/dist/backend/llvm/reference-writes.d.ts +4 -0
- package/dist/backend/llvm/reference-writes.js +143 -6
- package/dist/backend/llvm/reference-writes.js.map +1 -1
- package/dist/backend/llvm/reference-writes.test.d.ts +1 -0
- package/dist/backend/llvm/reference-writes.test.js +88 -0
- package/dist/backend/llvm/reference-writes.test.js.map +1 -0
- package/dist/backend/llvm/regex-matchers.d.ts +8 -0
- package/dist/backend/llvm/regex-matchers.js +33 -0
- package/dist/backend/llvm/regex-matchers.js.map +1 -1
- package/dist/backend/llvm/regex-matchers.test.js +23 -1
- package/dist/backend/llvm/regex-matchers.test.js.map +1 -1
- package/dist/backend/llvm/regions.d.ts +1 -1
- package/dist/backend/llvm/regions.js +9 -6
- package/dist/backend/llvm/regions.js.map +1 -1
- package/dist/backend/llvm/regions.test.js +1 -1
- package/dist/backend/llvm/shapes.d.ts +69 -43
- package/dist/backend/llvm/shapes.js +285 -21
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +37 -3
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/speculative-integers.d.ts +74 -0
- package/dist/backend/llvm/speculative-integers.js +571 -0
- package/dist/backend/llvm/speculative-integers.js.map +1 -0
- package/dist/backend/llvm/speculative-integers.test.d.ts +1 -0
- package/dist/backend/llvm/speculative-integers.test.js +148 -0
- package/dist/backend/llvm/speculative-integers.test.js.map +1 -0
- package/dist/backend/llvm/split-loops.js +2 -2
- package/dist/backend/llvm/split-loops.js.map +1 -1
- package/dist/backend/llvm/stack-objects.d.ts +26 -6
- package/dist/backend/llvm/stack-objects.js +133 -10
- package/dist/backend/llvm/stack-objects.js.map +1 -1
- package/dist/backend/llvm/stack-objects.test.js +55 -1
- package/dist/backend/llvm/stack-objects.test.js.map +1 -1
- package/dist/backend/llvm/stack-unions.test.js +1 -1
- package/dist/backend/llvm/string-construction.test.js +1 -1
- package/dist/backend/llvm/string-lifetimes.test.js +15 -14
- package/dist/backend/llvm/string-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/string-slices.d.ts +25 -0
- package/dist/backend/llvm/string-slices.js +207 -1
- package/dist/backend/llvm/string-slices.js.map +1 -1
- package/dist/backend/llvm/string-slices.test.js +139 -2
- package/dist/backend/llvm/string-slices.test.js.map +1 -1
- package/dist/backend/llvm/switch-dispatch.test.js +2 -2
- package/dist/backend/llvm/thread-slots.d.ts +5 -0
- package/dist/backend/llvm/thread-slots.js +142 -0
- package/dist/backend/llvm/thread-slots.js.map +1 -0
- package/dist/backend/llvm/thread-slots.test.d.ts +1 -0
- package/dist/backend/llvm/thread-slots.test.js +110 -0
- package/dist/backend/llvm/thread-slots.test.js.map +1 -0
- package/dist/backend/llvm/union-repr.d.ts +7 -7
- package/dist/backend/llvm/union-repr.js +18 -2
- package/dist/backend/llvm/union-repr.js.map +1 -1
- package/dist/backend/llvm/union-retype.test.js +17 -3
- package/dist/backend/llvm/union-retype.test.js.map +1 -1
- package/dist/backend/llvm/walkers.d.ts +2 -2
- package/dist/backend/llvm/walkers.js +51 -26
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/llvm/wasm-modules.d.ts +16 -0
- package/dist/backend/llvm/wasm-modules.js +66 -0
- package/dist/backend/llvm/wasm-modules.js.map +1 -0
- package/dist/backend/llvm/wrapping-sums.d.ts +7 -0
- package/dist/backend/llvm/wrapping-sums.js +11 -3
- package/dist/backend/llvm/wrapping-sums.js.map +1 -1
- package/dist/backend/mangle.d.ts +7 -0
- package/dist/backend/mangle.js +11 -0
- package/dist/backend/mangle.js.map +1 -1
- package/dist/backend/may-throw.d.ts +3 -0
- package/dist/backend/may-throw.js +6 -2
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/may-throw.test.js +1 -1
- package/dist/backend/native/contracts.d.ts +37 -0
- package/dist/backend/native/executable.js +192 -134
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/library.js +1 -0
- package/dist/backend/native/library.js.map +1 -1
- package/dist/backend/native/runtime-inputs.d.ts +1 -1
- package/dist/backend/native/runtime-inputs.js +2 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +30 -0
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/publication.test.js +1 -1
- package/dist/backend/runtime-pack-core.d.ts +9 -1
- package/dist/backend/runtime-pack-core.js +10 -1
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-native.js +1 -1
- package/dist/backend/runtime-pack-native.js.map +1 -1
- package/dist/backend/runtime-pack-native.test.d.ts +1 -0
- package/dist/backend/runtime-pack-native.test.js +31 -0
- package/dist/backend/runtime-pack-native.test.js.map +1 -0
- package/dist/backend/runtime-pack-targets.test.js +5 -0
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.d.ts +7 -3
- package/dist/backend/runtime-pack.js +12 -6
- package/dist/backend/runtime-pack.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +20 -6
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/stack-observations.d.ts +22 -0
- package/dist/backend/stack-observations.js +382 -0
- package/dist/backend/stack-observations.js.map +1 -0
- package/dist/backend/stack-observations.test.d.ts +1 -0
- package/dist/backend/stack-observations.test.js +233 -0
- package/dist/backend/stack-observations.test.js.map +1 -0
- package/dist/backend/target-diagnostics.js +8 -0
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/target-diagnostics.test.js +1 -1
- package/dist/backend/warm-cache.js +5 -0
- package/dist/backend/warm-cache.js.map +1 -1
- package/dist/backend/young-nursery.d.ts +7 -0
- package/dist/backend/young-nursery.js +10 -0
- package/dist/backend/young-nursery.js.map +1 -0
- package/dist/cli/command.js +44 -4
- package/dist/cli/command.js.map +1 -1
- package/dist/cli/usage.d.ts +11 -1
- package/dist/cli/usage.js +20 -1
- package/dist/cli/usage.js.map +1 -1
- package/dist/compat/fetch-profile.js +10 -1
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/compile-types.d.ts +13 -0
- package/dist/contracts/check.js +25 -6
- package/dist/contracts/check.js.map +1 -1
- package/dist/contracts/int32-elements.d.ts +115 -0
- package/dist/contracts/int32-elements.js +1179 -0
- package/dist/contracts/int32-elements.js.map +1 -0
- package/dist/coverage/report.d.ts +16 -0
- package/dist/coverage/report.js +182 -1
- package/dist/coverage/report.js.map +1 -1
- package/dist/coverage/surface-manifest.js +19 -6
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/coverage/verdict-cache.d.ts +2 -0
- package/dist/coverage/verdict-cache.js +12 -0
- package/dist/coverage/verdict-cache.js.map +1 -1
- package/dist/coverage/verdict-cache.test.js +2 -1
- package/dist/coverage/verdict-cache.test.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +11 -7
- package/dist/diagnostics/diagnostic.js +35 -23
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/envelope.d.ts +39 -2
- package/dist/diagnostics/envelope.js.map +1 -1
- package/dist/diagnostics/render.d.ts +7 -0
- package/dist/diagnostics/render.js +50 -13
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/diagnostics/render.test.d.ts +1 -0
- package/dist/diagnostics/render.test.js +49 -0
- package/dist/diagnostics/render.test.js.map +1 -0
- package/dist/executable/executable-cache.d.ts +17 -0
- package/dist/executable/executable-cache.js +13 -1
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +7 -1
- package/dist/executable/executable-cache.test.js.map +1 -1
- package/dist/executable/prepare.js +2 -1
- package/dist/executable/prepare.js.map +1 -1
- package/dist/frontend/analysis.js +6 -1
- package/dist/frontend/analysis.js.map +1 -1
- package/dist/frontend/builtin-modules.d.ts +16 -2
- package/dist/frontend/builtin-modules.js +40 -7
- package/dist/frontend/builtin-modules.js.map +1 -1
- package/dist/frontend/cjs-syntax.js +52 -51
- package/dist/frontend/cjs-syntax.js.map +1 -1
- package/dist/frontend/contract-types.d.ts +3 -0
- package/dist/frontend/contract-types.js +36 -7
- package/dist/frontend/contract-types.js.map +1 -1
- package/dist/frontend/experimental-import.d.ts +5 -1
- package/dist/frontend/experimental-import.js +26 -7
- package/dist/frontend/experimental-import.js.map +1 -1
- package/dist/frontend/fork-target.js +20 -22
- package/dist/frontend/fork-target.js.map +1 -1
- package/dist/frontend/fork-target.test.js +2 -1
- package/dist/frontend/fork-target.test.js.map +1 -1
- package/dist/frontend/function-completion.js +6 -6
- package/dist/frontend/function-completion.js.map +1 -1
- package/dist/frontend/helper-tokens.js +15 -3
- package/dist/frontend/helper-tokens.js.map +1 -1
- package/dist/frontend/helper-tokens.test.js +7 -1
- package/dist/frontend/helper-tokens.test.js.map +1 -1
- package/dist/frontend/inferred-js-diagnostics.js +14 -17
- package/dist/frontend/inferred-js-diagnostics.js.map +1 -1
- package/dist/frontend/input-tracker.d.ts +3 -0
- package/dist/frontend/input-tracker.js +32 -3
- package/dist/frontend/input-tracker.js.map +1 -1
- package/dist/frontend/lib-contract.js +36 -32
- package/dist/frontend/lib-contract.js.map +1 -1
- package/dist/frontend/lib-exports.js +3 -3
- package/dist/frontend/lib-exports.js.map +1 -1
- package/dist/frontend/lowering/array-values.d.ts +8 -3
- package/dist/frontend/lowering/array-values.js +60 -11
- package/dist/frontend/lowering/array-values.js.map +1 -1
- package/dist/frontend/lowering/assert-instances.js +4 -4
- package/dist/frontend/lowering/assert-instances.js.map +1 -1
- package/dist/frontend/lowering/assertion-identity.d.ts +12 -0
- package/dist/frontend/lowering/assertion-identity.js +70 -0
- package/dist/frontend/lowering/assertion-identity.js.map +1 -0
- package/dist/frontend/lowering/assertion-members.d.ts +28 -0
- package/dist/frontend/lowering/assertion-members.js +185 -0
- package/dist/frontend/lowering/assertion-members.js.map +1 -0
- package/dist/frontend/lowering/binding-analysis.js +27 -20
- package/dist/frontend/lowering/binding-analysis.js.map +1 -1
- package/dist/frontend/lowering/builtin-calls.js +72 -4
- package/dist/frontend/lowering/builtin-calls.js.map +1 -1
- package/dist/frontend/lowering/builtin-function-fences.d.ts +14 -0
- package/dist/frontend/lowering/builtin-function-fences.js +42 -0
- package/dist/frontend/lowering/builtin-function-fences.js.map +1 -0
- package/dist/frontend/lowering/builtins/arguments.js +1 -1
- package/dist/frontend/lowering/builtins/arguments.js.map +1 -1
- package/dist/frontend/lowering/builtins/async-context.js +53 -52
- package/dist/frontend/lowering/builtins/async-context.js.map +1 -1
- package/dist/frontend/lowering/builtins/atomics.js +6 -6
- package/dist/frontend/lowering/builtins/atomics.js.map +1 -1
- package/dist/frontend/lowering/builtins/blob.js +8 -6
- package/dist/frontend/lowering/builtins/blob.js.map +1 -1
- package/dist/frontend/lowering/builtins/builtin-class-dyn.d.ts +23 -0
- package/dist/frontend/lowering/builtins/builtin-class-dyn.js +156 -0
- package/dist/frontend/lowering/builtins/builtin-class-dyn.js.map +1 -0
- package/dist/frontend/lowering/builtins/callable-aliases.js +45 -6
- package/dist/frontend/lowering/builtins/callable-aliases.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-async.js +7 -7
- package/dist/frontend/lowering/builtins/child-process-async.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-methods.d.ts +6 -4
- package/dist/frontend/lowering/builtins/child-process-methods.js +310 -57
- package/dist/frontend/lowering/builtins/child-process-methods.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-sync.js +16 -10
- package/dist/frontend/lowering/builtins/child-process-sync.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process.d.ts +6 -4
- package/dist/frontend/lowering/builtins/child-process.js +85 -61
- package/dist/frontend/lowering/builtins/child-process.js.map +1 -1
- package/dist/frontend/lowering/builtins/class-values.d.ts +60 -0
- package/dist/frontend/lowering/builtins/class-values.js +226 -0
- package/dist/frontend/lowering/builtins/class-values.js.map +1 -0
- package/dist/frontend/lowering/builtins/compression.d.ts +18 -0
- package/dist/frontend/lowering/builtins/compression.js +230 -52
- package/dist/frontend/lowering/builtins/compression.js.map +1 -1
- package/dist/frontend/lowering/builtins/constants.d.ts +9 -1
- package/dist/frontend/lowering/builtins/constants.js +28 -7
- package/dist/frontend/lowering/builtins/constants.js.map +1 -1
- package/dist/frontend/lowering/builtins/crypto.d.ts +19 -0
- package/dist/frontend/lowering/builtins/crypto.js +223 -38
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
- package/dist/frontend/lowering/builtins/dates.d.ts +7 -1
- package/dist/frontend/lowering/builtins/dates.js +92 -16
- package/dist/frontend/lowering/builtins/dates.js.map +1 -1
- package/dist/frontend/lowering/builtins/disposable-stack.d.ts +18 -0
- package/dist/frontend/lowering/builtins/disposable-stack.js +137 -0
- package/dist/frontend/lowering/builtins/disposable-stack.js.map +1 -0
- package/dist/frontend/lowering/builtins/environment.js +3 -3
- package/dist/frontend/lowering/builtins/environment.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.d.ts +14 -10
- package/dist/frontend/lowering/builtins/errors.js +174 -6
- package/dist/frontend/lowering/builtins/errors.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +4 -0
- package/dist/frontend/lowering/builtins/filesystem-calls.js +136 -113
- package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem.d.ts +8 -0
- package/dist/frontend/lowering/builtins/filesystem.js +213 -76
- package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
- package/dist/frontend/lowering/builtins/fs-glob.js +3 -3
- package/dist/frontend/lowering/builtins/fs-glob.js.map +1 -1
- package/dist/frontend/lowering/builtins/fs-streams.js +10 -11
- package/dist/frontend/lowering/builtins/fs-streams.js.map +1 -1
- package/dist/frontend/lowering/builtins/hash-stream.d.ts +12 -0
- package/dist/frontend/lowering/builtins/hash-stream.js +80 -0
- package/dist/frontend/lowering/builtins/hash-stream.js.map +1 -0
- package/dist/frontend/lowering/builtins/ipc.js +45 -8
- package/dist/frontend/lowering/builtins/ipc.js.map +1 -1
- package/dist/frontend/lowering/builtins/json.js +232 -24
- package/dist/frontend/lowering/builtins/json.js.map +1 -1
- package/dist/frontend/lowering/builtins/key-object.js +4 -4
- package/dist/frontend/lowering/builtins/key-object.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-bindings.d.ts +8 -0
- package/dist/frontend/lowering/builtins/module-bindings.js +71 -22
- package/dist/frontend/lowering/builtins/module-bindings.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-calls.js +67 -46
- package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/module-resolution.d.ts +4 -3
- package/dist/frontend/lowering/builtins/module-resolution.js +24 -23
- package/dist/frontend/lowering/builtins/module-resolution.js.map +1 -1
- package/dist/frontend/lowering/builtins/navigator.d.ts +13 -0
- package/dist/frontend/lowering/builtins/navigator.js +40 -0
- package/dist/frontend/lowering/builtins/navigator.js.map +1 -0
- package/dist/frontend/lowering/builtins/net-address.d.ts +19 -0
- package/dist/frontend/lowering/builtins/net-address.js +156 -0
- package/dist/frontend/lowering/builtins/net-address.js.map +1 -0
- package/dist/frontend/lowering/builtins/numbers.js +25 -9
- package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
- package/dist/frontend/lowering/builtins/operating-system.d.ts +4 -0
- package/dist/frontend/lowering/builtins/operating-system.js +25 -12
- package/dist/frontend/lowering/builtins/operating-system.js.map +1 -1
- package/dist/frontend/lowering/builtins/performance.d.ts +12 -0
- package/dist/frontend/lowering/builtins/performance.js +259 -8
- package/dist/frontend/lowering/builtins/performance.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.d.ts +32 -1
- package/dist/frontend/lowering/builtins/process.js +468 -99
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/builtins/promises.d.ts +5 -1
- package/dist/frontend/lowering/builtins/promises.js +326 -43
- package/dist/frontend/lowering/builtins/promises.js.map +1 -1
- package/dist/frontend/lowering/builtins/promisify-callback.d.ts +37 -0
- package/dist/frontend/lowering/builtins/promisify-callback.js +320 -0
- package/dist/frontend/lowering/builtins/promisify-callback.js.map +1 -0
- package/dist/frontend/lowering/builtins/properties.js +37 -1
- package/dist/frontend/lowering/builtins/properties.js.map +1 -1
- package/dist/frontend/lowering/builtins/querystring.js +14 -14
- package/dist/frontend/lowering/builtins/querystring.js.map +1 -1
- package/dist/frontend/lowering/builtins/readline.d.ts +55 -13
- package/dist/frontend/lowering/builtins/readline.js +931 -69
- package/dist/frontend/lowering/builtins/readline.js.map +1 -1
- package/dist/frontend/lowering/builtins/receiver-types.js +3 -5
- package/dist/frontend/lowering/builtins/receiver-types.js.map +1 -1
- package/dist/frontend/lowering/builtins/reflection.js +16 -14
- package/dist/frontend/lowering/builtins/reflection.js.map +1 -1
- package/dist/frontend/lowering/builtins/runtime-constructor.d.ts +26 -0
- package/dist/frontend/lowering/builtins/runtime-constructor.js +165 -0
- package/dist/frontend/lowering/builtins/runtime-constructor.js.map +1 -0
- package/dist/frontend/lowering/builtins/strings.js +101 -12
- package/dist/frontend/lowering/builtins/strings.js.map +1 -1
- package/dist/frontend/lowering/builtins/text-codecs.js +41 -38
- package/dist/frontend/lowering/builtins/text-codecs.js.map +1 -1
- package/dist/frontend/lowering/builtins/timers.js +75 -30
- package/dist/frontend/lowering/builtins/timers.js.map +1 -1
- package/dist/frontend/lowering/builtins/url.d.ts +3 -0
- package/dist/frontend/lowering/builtins/url.js +120 -17
- package/dist/frontend/lowering/builtins/url.js.map +1 -1
- package/dist/frontend/lowering/builtins/util-types.js +20 -4
- package/dist/frontend/lowering/builtins/util-types.js.map +1 -1
- package/dist/frontend/lowering/builtins/v8.d.ts +11 -0
- package/dist/frontend/lowering/builtins/v8.js +105 -0
- package/dist/frontend/lowering/builtins/v8.js.map +1 -0
- package/dist/frontend/lowering/builtins/webassembly.d.ts +33 -0
- package/dist/frontend/lowering/builtins/webassembly.js +388 -0
- package/dist/frontend/lowering/builtins/webassembly.js.map +1 -0
- package/dist/frontend/lowering/builtins/webcrypto.d.ts +20 -0
- package/dist/frontend/lowering/builtins/webcrypto.js +112 -0
- package/dist/frontend/lowering/builtins/webcrypto.js.map +1 -0
- package/dist/frontend/lowering/builtins/workers.d.ts +16 -0
- package/dist/frontend/lowering/builtins/workers.js +246 -3
- package/dist/frontend/lowering/builtins/workers.js.map +1 -1
- package/dist/frontend/lowering/call-arguments.js +69 -14
- package/dist/frontend/lowering/call-arguments.js.map +1 -1
- package/dist/frontend/lowering/call-signatures.d.ts +19 -1
- package/dist/frontend/lowering/call-signatures.js +254 -47
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/checked-promise-all.d.ts +3 -0
- package/dist/frontend/lowering/checked-promise-all.js +1 -1
- package/dist/frontend/lowering/checked-promise-all.js.map +1 -1
- package/dist/frontend/lowering/cjs-exports-object.d.ts +53 -0
- package/dist/frontend/lowering/cjs-exports-object.js +528 -0
- package/dist/frontend/lowering/cjs-exports-object.js.map +1 -0
- package/dist/frontend/lowering/cjs-inline-require.d.ts +86 -0
- package/dist/frontend/lowering/cjs-inline-require.js +314 -0
- package/dist/frontend/lowering/cjs-inline-require.js.map +1 -0
- package/dist/frontend/lowering/cjs-tsc-interop.d.ts +28 -0
- package/dist/frontend/lowering/cjs-tsc-interop.js +208 -0
- package/dist/frontend/lowering/cjs-tsc-interop.js.map +1 -0
- package/dist/frontend/lowering/class-attributes.d.ts +19 -0
- package/dist/frontend/lowering/class-attributes.js +378 -0
- package/dist/frontend/lowering/class-attributes.js.map +1 -0
- package/dist/frontend/lowering/class-callbacks.d.ts +3 -1
- package/dist/frontend/lowering/class-callbacks.js +21 -10
- package/dist/frontend/lowering/class-callbacks.js.map +1 -1
- package/dist/frontend/lowering/class-construction.js +49 -4
- package/dist/frontend/lowering/class-construction.js.map +1 -1
- package/dist/frontend/lowering/class-descriptors.d.ts +2 -0
- package/dist/frontend/lowering/class-descriptors.js +8 -8
- package/dist/frontend/lowering/class-descriptors.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +64 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +1115 -89
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-instance-constructor.js +1 -1
- package/dist/frontend/lowering/class-instance-constructor.js.map +1 -1
- package/dist/frontend/lowering/class-iterables.d.ts +11 -0
- package/dist/frontend/lowering/class-iterables.js +31 -0
- package/dist/frontend/lowering/class-iterables.js.map +1 -0
- package/dist/frontend/lowering/class-method-mutations.js +73 -35
- package/dist/frontend/lowering/class-method-mutations.js.map +1 -1
- package/dist/frontend/lowering/class-method-values.js +56 -10
- package/dist/frontend/lowering/class-method-values.js.map +1 -1
- package/dist/frontend/lowering/class-protocol-dispatch.js +24 -22
- package/dist/frontend/lowering/class-protocol-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-protocols.d.ts +55 -0
- package/dist/frontend/lowering/class-protocols.js +738 -22
- package/dist/frontend/lowering/class-protocols.js.map +1 -1
- package/dist/frontend/lowering/class-prototypes.d.ts +6 -0
- package/dist/frontend/lowering/class-prototypes.js +80 -18
- package/dist/frontend/lowering/class-prototypes.js.map +1 -1
- package/dist/frontend/lowering/class-runtime-statics.js +1 -1
- package/dist/frontend/lowering/class-runtime-statics.js.map +1 -1
- package/dist/frontend/lowering/class-static-data.js +2 -2
- package/dist/frontend/lowering/class-static-data.js.map +1 -1
- package/dist/frontend/lowering/class-to-primitive.d.ts +25 -0
- package/dist/frontend/lowering/class-to-primitive.js +261 -0
- package/dist/frontend/lowering/class-to-primitive.js.map +1 -0
- package/dist/frontend/lowering/class-unions.d.ts +25 -0
- package/dist/frontend/lowering/class-unions.js +102 -1
- package/dist/frontend/lowering/class-unions.js.map +1 -1
- package/dist/frontend/lowering/code-generation.d.ts +14 -0
- package/dist/frontend/lowering/code-generation.js +127 -0
- package/dist/frontend/lowering/code-generation.js.map +1 -0
- package/dist/frontend/lowering/coercions/function-adapters.d.ts +16 -2
- package/dist/frontend/lowering/coercions/function-adapters.js +145 -3
- package/dist/frontend/lowering/coercions/function-adapters.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural-plans.js +25 -3
- package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural.js +35 -3
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/coercions/unions.d.ts +15 -0
- package/dist/frontend/lowering/coercions/unions.js +57 -1
- package/dist/frontend/lowering/coercions/unions.js.map +1 -1
- package/dist/frontend/lowering/collection-ingestion.js +2 -2
- package/dist/frontend/lowering/collection-ingestion.js.map +1 -1
- package/dist/frontend/lowering/collection-narrowing.js +2 -4
- package/dist/frontend/lowering/collection-narrowing.js.map +1 -1
- package/dist/frontend/lowering/construction-escapes.js +8 -8
- package/dist/frontend/lowering/construction-escapes.js.map +1 -1
- package/dist/frontend/lowering/construction-escapes.test.js +4 -4
- package/dist/frontend/lowering/construction-escapes.test.js.map +1 -1
- package/dist/frontend/lowering/constructor-returns.d.ts +61 -0
- package/dist/frontend/lowering/constructor-returns.js +477 -0
- package/dist/frontend/lowering/constructor-returns.js.map +1 -0
- package/dist/frontend/lowering/containers/array-callback-call.js +1 -1
- package/dist/frontend/lowering/containers/array-callback-call.js.map +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.d.ts +9 -0
- package/dist/frontend/lowering/containers/array-callbacks.js +266 -100
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-concat.js +1 -1
- package/dist/frontend/lowering/containers/array-concat.js.map +1 -1
- package/dist/frontend/lowering/containers/array-construction.d.ts +0 -1
- package/dist/frontend/lowering/containers/array-construction.js +51 -13
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-from-async.d.ts +19 -0
- package/dist/frontend/lowering/containers/array-from-async.js +427 -0
- package/dist/frontend/lowering/containers/array-from-async.js.map +1 -0
- package/dist/frontend/lowering/containers/array-methods.js +89 -77
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/array-pipelines.js +1 -0
- package/dist/frontend/lowering/containers/array-pipelines.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.js +161 -101
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/callback-arguments.d.ts +9 -1
- package/dist/frontend/lowering/containers/callback-arguments.js +55 -5
- package/dist/frontend/lowering/containers/callback-arguments.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-grouping.d.ts +7 -8
- package/dist/frontend/lowering/containers/collection-grouping.js +219 -27
- package/dist/frontend/lowering/containers/collection-grouping.js.map +1 -1
- package/dist/frontend/lowering/containers/collection-methods.js +81 -48
- package/dist/frontend/lowering/containers/collection-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/dynamic-receivers.js +1 -1
- package/dist/frontend/lowering/containers/dynamic-receivers.js.map +1 -1
- package/dist/frontend/lowering/containers/exec-result-uses.js +2 -2
- package/dist/frontend/lowering/containers/exec-result-uses.js.map +1 -1
- package/dist/frontend/lowering/containers/for-of.d.ts +6 -0
- package/dist/frontend/lowering/containers/for-of.js +19 -19
- package/dist/frontend/lowering/containers/for-of.js.map +1 -1
- package/dist/frontend/lowering/containers/indexed-objects.js +142 -57
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/containers/iterator-helpers.d.ts +53 -4
- package/dist/frontend/lowering/containers/iterator-helpers.js +1581 -462
- package/dist/frontend/lowering/containers/iterator-helpers.js.map +1 -1
- package/dist/frontend/lowering/containers/match-row-uses.d.ts +17 -0
- package/dist/frontend/lowering/containers/match-row-uses.js +264 -0
- package/dist/frontend/lowering/containers/match-row-uses.js.map +1 -0
- package/dist/frontend/lowering/containers/string-and-regexp.d.ts +14 -0
- package/dist/frontend/lowering/containers/string-and-regexp.js +419 -30
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/containers/string-replacement.js +1 -1
- package/dist/frontend/lowering/containers/string-replacement.js.map +1 -1
- package/dist/frontend/lowering/cycle-initialization.d.ts +4 -0
- package/dist/frontend/lowering/cycle-initialization.js +39 -0
- package/dist/frontend/lowering/cycle-initialization.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.js +47 -43
- package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -1
- package/dist/frontend/lowering/devirtualize.d.ts +1 -1
- package/dist/frontend/lowering/devirtualize.js +27 -7
- package/dist/frontend/lowering/devirtualize.js.map +1 -1
- package/dist/frontend/lowering/divergences.d.ts +0 -5
- package/dist/frontend/lowering/divergences.js +238 -128
- package/dist/frontend/lowering/divergences.js.map +1 -1
- package/dist/frontend/lowering/dyn-streams.d.ts +25 -0
- package/dist/frontend/lowering/dyn-streams.js +257 -0
- package/dist/frontend/lowering/dyn-streams.js.map +1 -0
- package/dist/frontend/lowering/error-methods.js +4 -1
- package/dist/frontend/lowering/error-methods.js.map +1 -1
- package/dist/frontend/lowering/error-name-order.d.ts +19 -0
- package/dist/frontend/lowering/error-name-order.js +93 -0
- package/dist/frontend/lowering/error-name-order.js.map +1 -0
- package/dist/frontend/lowering/expressions/array-literals.d.ts +21 -0
- package/dist/frontend/lowering/expressions/array-literals.js +703 -0
- package/dist/frontend/lowering/expressions/array-literals.js.map +1 -0
- package/dist/frontend/lowering/expressions/binary.d.ts +35 -0
- package/dist/frontend/lowering/expressions/binary.js +2483 -0
- package/dist/frontend/lowering/expressions/binary.js.map +1 -0
- package/dist/frontend/lowering/expressions/element-access.d.ts +31 -0
- package/dist/frontend/lowering/expressions/element-access.js +1797 -0
- package/dist/frontend/lowering/expressions/element-access.js.map +1 -0
- package/dist/frontend/lowering/expressions/evaluation-safety.js +4 -3
- package/dist/frontend/lowering/expressions/evaluation-safety.js.map +1 -1
- package/dist/frontend/lowering/expressions/hosted-narrowing.d.ts +38 -0
- package/dist/frontend/lowering/expressions/hosted-narrowing.js +160 -0
- package/dist/frontend/lowering/expressions/hosted-narrowing.js.map +1 -0
- package/dist/frontend/lowering/expressions/identifiers.d.ts +4 -0
- package/dist/frontend/lowering/expressions/identifiers.js +830 -0
- package/dist/frontend/lowering/expressions/identifiers.js.map +1 -0
- package/dist/frontend/lowering/expressions/keyed-field-targets.d.ts +40 -0
- package/dist/frontend/lowering/expressions/keyed-field-targets.js +226 -0
- package/dist/frontend/lowering/expressions/keyed-field-targets.js.map +1 -0
- package/dist/frontend/lowering/expressions/narrowing.d.ts +37 -0
- package/dist/frontend/lowering/expressions/narrowing.js +1322 -0
- package/dist/frontend/lowering/expressions/narrowing.js.map +1 -0
- package/dist/frontend/lowering/expressions/native-proxy.js +4 -4
- package/dist/frontend/lowering/expressions/native-proxy.js.map +1 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js +45 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.d.ts +10 -0
- package/dist/frontend/lowering/expressions/object-literals.js +253 -85
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/expressions/optional-chains.d.ts +2 -1
- package/dist/frontend/lowering/expressions/optional-chains.js +91 -14
- package/dist/frontend/lowering/expressions/optional-chains.js.map +1 -1
- package/dist/frontend/lowering/expressions/property-access.d.ts +110 -0
- package/dist/frontend/lowering/expressions/property-access.js +3544 -0
- package/dist/frontend/lowering/expressions/property-access.js.map +1 -0
- package/dist/frontend/lowering/expressions/relational.d.ts +28 -0
- package/dist/frontend/lowering/expressions/relational.js +1679 -0
- package/dist/frontend/lowering/expressions/relational.js.map +1 -0
- package/dist/frontend/lowering/expressions/typeof.d.ts +22 -0
- package/dist/frontend/lowering/expressions/typeof.js +538 -0
- package/dist/frontend/lowering/expressions/typeof.js.map +1 -0
- package/dist/frontend/lowering/expressions/union-fields.js +1 -1
- package/dist/frontend/lowering/expressions/union-fields.js.map +1 -1
- package/dist/frontend/lowering/expressions/updates.d.ts +21 -0
- package/dist/frontend/lowering/expressions/updates.js +780 -0
- package/dist/frontend/lowering/expressions/updates.js.map +1 -0
- package/dist/frontend/lowering/function-context.d.ts +10 -0
- package/dist/frontend/lowering/function-context.js +11 -1
- package/dist/frontend/lowering/function-context.js.map +1 -1
- package/dist/frontend/lowering/function-returns.js +52 -28
- package/dist/frontend/lowering/function-returns.js.map +1 -1
- package/dist/frontend/lowering/general-streams.d.ts +25 -0
- package/dist/frontend/lowering/general-streams.js +108 -0
- package/dist/frontend/lowering/general-streams.js.map +1 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.d.ts +7 -0
- package/dist/frontend/lowering/generator-dynamic-dispatch.js +172 -69
- package/dist/frontend/lowering/generator-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/generic-functions.d.ts +39 -0
- package/dist/frontend/lowering/generic-functions.js +393 -75
- package/dist/frontend/lowering/generic-functions.js.map +1 -1
- package/dist/frontend/lowering/import-meta.js +2 -2
- package/dist/frontend/lowering/import-meta.js.map +1 -1
- package/dist/frontend/lowering/intern-tables.js +10 -9
- package/dist/frontend/lowering/intern-tables.js.map +1 -1
- package/dist/frontend/lowering/iterator-adapters.d.ts +19 -0
- package/dist/frontend/lowering/iterator-adapters.js +331 -3
- package/dist/frontend/lowering/iterator-adapters.js.map +1 -1
- package/dist/frontend/lowering/js-class-fields.d.ts +28 -0
- package/dist/frontend/lowering/js-class-fields.js +170 -0
- package/dist/frontend/lowering/js-class-fields.js.map +1 -0
- package/dist/frontend/lowering/js-dynamic-objects.d.ts +15 -0
- package/dist/frontend/lowering/js-dynamic-objects.js +299 -0
- package/dist/frontend/lowering/js-dynamic-objects.js.map +1 -0
- package/dist/frontend/lowering/js-dynamic-objects.test.d.ts +1 -0
- package/dist/frontend/lowering/js-dynamic-objects.test.js +35 -0
- package/dist/frontend/lowering/js-dynamic-objects.test.js.map +1 -0
- package/dist/frontend/lowering/json-require.d.ts +22 -0
- package/dist/frontend/lowering/json-require.js +131 -0
- package/dist/frontend/lowering/json-require.js.map +1 -0
- package/dist/frontend/lowering/key-order-witness.d.ts +44 -0
- package/dist/frontend/lowering/key-order-witness.js +641 -0
- package/dist/frontend/lowering/key-order-witness.js.map +1 -0
- package/dist/frontend/lowering/key-order-witness.test.d.ts +1 -0
- package/dist/frontend/lowering/key-order-witness.test.js +239 -0
- package/dist/frontend/lowering/key-order-witness.test.js.map +1 -0
- package/dist/frontend/lowering/lifetime-regions.js +7 -7
- package/dist/frontend/lowering/lifetime-regions.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +61 -60
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.d.ts +10 -1
- package/dist/frontend/lowering/lower-async-iteration.js +34 -6
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-builtin-values.d.ts +5 -0
- package/dist/frontend/lowering/lower-builtin-values.js +32 -3
- package/dist/frontend/lowering/lower-builtin-values.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +1298 -452
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +50 -3
- package/dist/frontend/lowering/lower-classes.js +1499 -456
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +4 -2
- package/dist/frontend/lowering/lower-comptime.js +111 -13
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-console.js +13 -11
- package/dist/frontend/lowering/lower-console.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.d.ts +10 -0
- package/dist/frontend/lowering/lower-dgram.js +179 -8
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-enums.js +113 -14
- package/dist/frontend/lowering/lower-enums.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.d.ts +16 -7
- package/dist/frontend/lowering/lower-event-emitter.js +268 -71
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-event-target.js +2 -2
- package/dist/frontend/lowering/lower-event-target.js.map +1 -1
- package/dist/frontend/lowering/lower-expando.js +17 -13
- package/dist/frontend/lowering/lower-expando.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +188 -186
- package/dist/frontend/lowering/lower-exprs.js +1493 -12407
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-functions.js +68 -22
- package/dist/frontend/lowering/lower-functions.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +6 -0
- package/dist/frontend/lowering/lower-generators.js +29 -16
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-global-value.js +5 -1
- package/dist/frontend/lowering/lower-global-value.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +354 -99
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +23 -20
- package/dist/frontend/lowering/lower-mixins.js.map +1 -1
- package/dist/frontend/lowering/lower-mock.d.ts +19 -2
- package/dist/frontend/lowering/lower-mock.js +557 -74
- package/dist/frontend/lowering/lower-mock.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +268 -61
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +6 -0
- package/dist/frontend/lowering/lower-namespaces.js +45 -33
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-node-module.d.ts +16 -0
- package/dist/frontend/lowering/lower-node-module.js +147 -14
- package/dist/frontend/lowering/lower-node-module.js.map +1 -1
- package/dist/frontend/lowering/lower-server.d.ts +6 -6
- package/dist/frontend/lowering/lower-server.js +638 -105
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stdlib.d.ts +4 -0
- package/dist/frontend/lowering/lower-stdlib.js +151 -109
- package/dist/frontend/lowering/lower-stdlib.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +28 -2
- package/dist/frontend/lowering/lower-stmts.js +1589 -398
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +4 -3
- package/dist/frontend/lowering/lower-stream.js +714 -75
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.d.ts +3 -0
- package/dist/frontend/lowering/lower-test.js +574 -100
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lower-timers.js +80 -32
- package/dist/frontend/lowering/lower-timers.js.map +1 -1
- package/dist/frontend/lowering/lower-url.js +1 -1
- package/dist/frontend/lowering/lower-url.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +409 -26
- package/dist/frontend/lowering/lowerer.js +1918 -305
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/lowerer.test.js +10 -4
- package/dist/frontend/lowering/lowerer.test.js.map +1 -1
- package/dist/frontend/lowering/maybe-promise.d.ts +46 -0
- package/dist/frontend/lowering/maybe-promise.js +249 -0
- package/dist/frontend/lowering/maybe-promise.js.map +1 -0
- package/dist/frontend/lowering/module-member-this.d.ts +3 -0
- package/dist/frontend/lowering/module-member-this.js +262 -0
- package/dist/frontend/lowering/module-member-this.js.map +1 -0
- package/dist/frontend/lowering/module-namespace-elements.js +1 -1
- package/dist/frontend/lowering/module-namespace-elements.js.map +1 -1
- package/dist/frontend/lowering/nan-coded-reads.d.ts +3 -0
- package/dist/frontend/lowering/nan-coded-reads.js +45 -32
- package/dist/frontend/lowering/nan-coded-reads.js.map +1 -1
- package/dist/frontend/lowering/narrowing-stability.d.ts +18 -3
- package/dist/frontend/lowering/narrowing-stability.js +104 -32
- package/dist/frontend/lowering/narrowing-stability.js.map +1 -1
- package/dist/frontend/lowering/native-ffi.js +11 -11
- package/dist/frontend/lowering/native-ffi.js.map +1 -1
- package/dist/frontend/lowering/null-prototype.d.ts +13 -0
- package/dist/frontend/lowering/null-prototype.js +33 -0
- package/dist/frontend/lowering/null-prototype.js.map +1 -0
- package/dist/frontend/lowering/object-factory-new.js +6 -8
- package/dist/frontend/lowering/object-factory-new.js.map +1 -1
- package/dist/frontend/lowering/private-brands.d.ts +46 -0
- package/dist/frontend/lowering/private-brands.js +265 -0
- package/dist/frontend/lowering/private-brands.js.map +1 -0
- package/dist/frontend/lowering/promise-executor-adapter.d.ts +11 -0
- package/dist/frontend/lowering/promise-executor-adapter.js +87 -0
- package/dist/frontend/lowering/promise-executor-adapter.js.map +1 -0
- package/dist/frontend/lowering/require-initialization.d.ts +32 -0
- package/dist/frontend/lowering/require-initialization.js +246 -0
- package/dist/frontend/lowering/require-initialization.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-bounds.js +7 -7
- package/dist/frontend/lowering/runtime-optional-bounds.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-elements.js +12 -12
- package/dist/frontend/lowering/runtime-optional-elements.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-guards.js +10 -10
- package/dist/frontend/lowering/runtime-optional-guards.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-guards.test.js +1 -1
- package/dist/frontend/lowering/runtime-optional-guards.test.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-ownership.js +10 -9
- package/dist/frontend/lowering/runtime-optional-ownership.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-provenance.js +2 -2
- package/dist/frontend/lowering/runtime-optional-provenance.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-records.d.ts +35 -0
- package/dist/frontend/lowering/runtime-optional-records.js +205 -32
- package/dist/frontend/lowering/runtime-optional-records.js.map +1 -1
- package/dist/frontend/lowering/runtime-optional-records.test.js +19 -1
- package/dist/frontend/lowering/runtime-optional-records.test.js.map +1 -1
- package/dist/frontend/lowering/sanitize-class-types.test.js +2 -2
- package/dist/frontend/lowering/split-consumers.js +4 -4
- package/dist/frontend/lowering/split-consumers.js.map +1 -1
- package/dist/frontend/lowering/static-function-names.d.ts +28 -0
- package/dist/frontend/lowering/static-function-names.js +212 -0
- package/dist/frontend/lowering/static-function-names.js.map +1 -0
- package/dist/frontend/lowering/static-this.js +6 -6
- package/dist/frontend/lowering/static-this.js.map +1 -1
- package/dist/frontend/lowering/strict-mode.d.ts +5 -0
- package/dist/frontend/lowering/strict-mode.js +31 -0
- package/dist/frontend/lowering/strict-mode.js.map +1 -0
- package/dist/frontend/lowering/string-index-bounds.js +10 -10
- package/dist/frontend/lowering/string-index-bounds.js.map +1 -1
- package/dist/frontend/lowering/string-index.d.ts +12 -0
- package/dist/frontend/lowering/string-index.js +72 -1
- package/dist/frontend/lowering/string-index.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +15 -6
- package/dist/frontend/lowering/surfaces.js +278 -45
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/symbol-fields.d.ts +7 -0
- package/dist/frontend/lowering/symbol-fields.js +204 -36
- package/dist/frontend/lowering/symbol-fields.js.map +1 -1
- package/dist/frontend/lowering/symbol-methods.d.ts +2 -1
- package/dist/frontend/lowering/symbol-methods.js +24 -6
- package/dist/frontend/lowering/symbol-methods.js.map +1 -1
- package/dist/frontend/lowering/thread-slots.d.ts +13 -0
- package/dist/frontend/lowering/thread-slots.js +208 -0
- package/dist/frontend/lowering/thread-slots.js.map +1 -0
- package/dist/frontend/lowering/typed-arguments.d.ts +74 -0
- package/dist/frontend/lowering/typed-arguments.js +472 -0
- package/dist/frontend/lowering/typed-arguments.js.map +1 -0
- package/dist/frontend/lowering/union-retag.d.ts +8 -0
- package/dist/frontend/lowering/union-retag.js +27 -0
- package/dist/frontend/lowering/union-retag.js.map +1 -1
- package/dist/frontend/lowering/union-retag.test.js +24 -1
- package/dist/frontend/lowering/union-retag.test.js.map +1 -1
- package/dist/frontend/lowering/var-hoisting.js +6 -6
- package/dist/frontend/lowering/var-hoisting.js.map +1 -1
- package/dist/frontend/lowering/width-lift.d.ts +4 -0
- package/dist/frontend/mock-shapes.d.ts +5 -0
- package/dist/frontend/mock-shapes.js +39 -7
- package/dist/frontend/mock-shapes.js.map +1 -1
- package/dist/frontend/module-source-candidates.js +1 -1
- package/dist/frontend/module-source-candidates.js.map +1 -1
- package/dist/frontend/module-source-candidates.test.js +2 -1
- package/dist/frontend/module-source-candidates.test.js.map +1 -1
- package/dist/frontend/module-syntax.js +8 -8
- package/dist/frontend/module-syntax.js.map +1 -1
- package/dist/frontend/npm-static-bundled-chunks.d.ts +51 -0
- package/dist/frontend/npm-static-bundled-chunks.js +810 -0
- package/dist/frontend/npm-static-bundled-chunks.js.map +1 -0
- package/dist/frontend/npm-static-bundled-chunks.test.d.ts +1 -0
- package/dist/frontend/npm-static-bundled-chunks.test.js +287 -0
- package/dist/frontend/npm-static-bundled-chunks.test.js.map +1 -0
- package/dist/frontend/npm-static-bundled-cjs.js +24 -23
- package/dist/frontend/npm-static-bundled-cjs.js.map +1 -1
- package/dist/frontend/npm-static-bundled-esm.d.ts +9 -0
- package/dist/frontend/npm-static-bundled-esm.js +768 -0
- package/dist/frontend/npm-static-bundled-esm.js.map +1 -0
- package/dist/frontend/npm-static-bundled-esm.test.d.ts +1 -0
- package/dist/frontend/npm-static-bundled-esm.test.js +207 -0
- package/dist/frontend/npm-static-bundled-esm.test.js.map +1 -0
- package/dist/frontend/npm-static-cjs-exports-alias.d.ts +2 -0
- package/dist/frontend/npm-static-cjs-exports-alias.js +186 -0
- package/dist/frontend/npm-static-cjs-exports-alias.js.map +1 -0
- package/dist/frontend/npm-static-cjs-exports-alias.test.d.ts +1 -0
- package/dist/frontend/npm-static-cjs-exports-alias.test.js +73 -0
- package/dist/frontend/npm-static-cjs-exports-alias.test.js.map +1 -0
- package/dist/frontend/npm-static-cjs-exports-var.d.ts +2 -0
- package/dist/frontend/npm-static-cjs-exports-var.js +236 -0
- package/dist/frontend/npm-static-cjs-exports-var.js.map +1 -0
- package/dist/frontend/npm-static-declaration-syntax.js +102 -101
- package/dist/frontend/npm-static-declaration-syntax.js.map +1 -1
- package/dist/frontend/npm-static-prune.js +36 -24
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-host.d.ts +4 -1
- package/dist/frontend/npm-static-rewrite-host.js +14 -3
- package/dist/frontend/npm-static-rewrite-host.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-syntax.d.ts +19 -0
- package/dist/frontend/npm-static-rewrite-syntax.js +274 -101
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -1
- package/dist/frontend/npm-static-subtyping.js +7 -9
- package/dist/frontend/npm-static-subtyping.js.map +1 -1
- package/dist/frontend/npm-static.d.ts +17 -1
- package/dist/frontend/npm-static.js +167 -16
- package/dist/frontend/npm-static.js.map +1 -1
- package/dist/frontend/npm-static.test.js +22 -1
- package/dist/frontend/npm-static.test.js.map +1 -1
- package/dist/frontend/pipeline.js +164 -26
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/pipeline.test.js +22 -1
- package/dist/frontend/pipeline.test.js.map +1 -1
- package/dist/frontend/program-analysis.d.ts +6 -1
- package/dist/frontend/program-analysis.js +7 -0
- package/dist/frontend/program-analysis.js.map +1 -1
- package/dist/frontend/program.d.ts +92 -2
- package/dist/frontend/program.js +1557 -254
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +76 -6
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/resolve.js +36 -2
- package/dist/frontend/resolve.js.map +1 -1
- package/dist/frontend/resolve.test.js +49 -0
- package/dist/frontend/resolve.test.js.map +1 -1
- package/dist/frontend/services.d.ts +20 -1
- package/dist/frontend/services.js +40 -3
- package/dist/frontend/services.js.map +1 -1
- package/dist/frontend/services.test.js +2 -1
- package/dist/frontend/services.test.js.map +1 -1
- package/dist/frontend/threads-import.js +1 -1
- package/dist/frontend/threads-import.js.map +1 -1
- package/dist/frontend/tier-analysis.d.ts +71 -0
- package/dist/frontend/tier-analysis.js +522 -0
- package/dist/frontend/tier-analysis.js.map +1 -0
- package/dist/frontend/ts7/api-conformance.d.ts +234 -0
- package/dist/frontend/ts7/api-conformance.js +7 -0
- package/dist/frontend/ts7/api-conformance.js.map +1 -0
- package/dist/frontend/ts7/ast-guards.generated.js +2 -1
- package/dist/frontend/ts7/ast-guards.generated.js.map +1 -1
- package/dist/frontend/ts7/ast-node.d.ts +47 -25
- package/dist/frontend/ts7/ast-node.js +64 -18
- package/dist/frontend/ts7/ast-node.js.map +1 -1
- package/dist/frontend/ts7/ast-node.test.js +36 -12
- package/dist/frontend/ts7/ast-node.test.js.map +1 -1
- package/dist/frontend/ts7/ast-types.d.ts +10 -3
- package/dist/frontend/ts7/ast-types.generated.d.ts +39 -39
- package/dist/frontend/ts7/ast.d.ts +1 -0
- package/dist/frontend/ts7/ast.js +3 -2
- package/dist/frontend/ts7/ast.js.map +1 -1
- package/dist/frontend/ts7/checker-backend.d.ts +23 -0
- package/dist/frontend/ts7/checker-backend.js +88 -0
- package/dist/frontend/ts7/checker-backend.js.map +1 -0
- package/dist/frontend/ts7/checker-backend.test.d.ts +1 -0
- package/dist/frontend/ts7/checker-backend.test.js +63 -0
- package/dist/frontend/ts7/checker-backend.test.js.map +1 -0
- package/dist/frontend/ts7/checker-cache.d.ts +0 -3
- package/dist/frontend/ts7/checker-cache.js +0 -6
- package/dist/frontend/ts7/checker-cache.js.map +1 -1
- package/dist/frontend/ts7/checker.d.ts +18 -11
- package/dist/frontend/ts7/checker.js +42 -55
- package/dist/frontend/ts7/checker.js.map +1 -1
- package/dist/frontend/ts7/checker.test.js +10 -7
- package/dist/frontend/ts7/checker.test.js.map +1 -1
- package/dist/frontend/ts7/diagnostic.d.ts +19 -0
- package/dist/frontend/ts7/diagnostic.js +22 -0
- package/dist/frontend/ts7/diagnostic.js.map +1 -0
- package/dist/frontend/ts7/node-functions.d.ts +8 -0
- package/dist/frontend/ts7/node-functions.js +18 -0
- package/dist/frontend/ts7/node-functions.js.map +1 -0
- package/dist/frontend/ts7/program-host.d.ts +5 -1
- package/dist/frontend/ts7/program-host.js +12 -0
- package/dist/frontend/ts7/program-host.js.map +1 -1
- package/dist/frontend/ts7/rpc-api.d.ts +5 -1
- package/dist/frontend/ts7/rpc-api.js +8 -1
- package/dist/frontend/ts7/rpc-api.js.map +1 -1
- package/dist/frontend/ts7/semantic-checker.d.ts +13 -6
- package/dist/frontend/ts7/semantic-checker.js +26 -8
- package/dist/frontend/ts7/semantic-checker.js.map +1 -1
- package/dist/frontend/ts7/semantic-checker.test.js +12 -9
- package/dist/frontend/ts7/semantic-checker.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.d.ts +54 -24
- package/dist/frontend/ts7/semantic-model.js +88 -16
- package/dist/frontend/ts7/semantic-model.js.map +1 -1
- package/dist/frontend/ts7/semantic-model.test.js +4 -4
- package/dist/frontend/ts7/semantic-model.test.js.map +1 -1
- package/dist/frontend/ts7/semantic-types.d.ts +7 -3
- package/dist/frontend/ts7/semantic-types.js +1 -1
- package/dist/frontend/ts7/semantic-types.js.map +1 -1
- package/dist/frontend/ts7/session.d.ts +11 -11
- package/dist/frontend/ts7/session.js +8 -5
- package/dist/frontend/ts7/session.js.map +1 -1
- package/dist/frontend/ts7/session.test.js +9 -5
- package/dist/frontend/ts7/session.test.js.map +1 -1
- package/dist/frontend/ts7/source-parser.d.ts +6 -2
- package/dist/frontend/ts7/source-parser.js +24 -3
- package/dist/frontend/ts7/source-parser.js.map +1 -1
- package/dist/frontend/ts7/source-parser.test.js +38 -17
- package/dist/frontend/ts7/source-parser.test.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +122 -2
- package/dist/frontend/type-mapper.js +2612 -695
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/frontend/type-only-imports.d.ts +28 -0
- package/dist/frontend/type-only-imports.js +122 -0
- package/dist/frontend/type-only-imports.js.map +1 -0
- package/dist/frontend/worker-target.js +8 -8
- package/dist/frontend/worker-target.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +47 -10
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.js +4 -2
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/api.d.ts +1 -1
- package/dist/ir/api.js +1 -1
- package/dist/ir/api.js.map +1 -1
- package/dist/ir/array-length-stability.d.ts +30 -0
- package/dist/ir/array-length-stability.js +236 -0
- package/dist/ir/array-length-stability.js.map +1 -0
- package/dist/ir/array-length-stability.test.d.ts +1 -0
- package/dist/ir/array-length-stability.test.js +113 -0
- package/dist/ir/array-length-stability.test.js.map +1 -0
- package/dist/ir/build.d.ts +2 -2
- package/dist/ir/build.js +1 -1
- package/dist/ir/build.js.map +1 -1
- package/dist/ir/builtin-effects.js +139 -0
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +1 -1
- package/dist/ir/builtin-signatures.js +655 -25
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/byte-numbers.js +3 -0
- package/dist/ir/byte-numbers.js.map +1 -1
- package/dist/ir/callback-specialization.d.ts +37 -0
- package/dist/ir/callback-specialization.js +459 -0
- package/dist/ir/callback-specialization.js.map +1 -0
- package/dist/ir/callback-specialization.test.d.ts +1 -0
- package/dist/ir/callback-specialization.test.js +208 -0
- package/dist/ir/callback-specialization.test.js.map +1 -0
- package/dist/ir/capture-values.d.ts +0 -1
- package/dist/ir/capture-values.js +51 -40
- package/dist/ir/capture-values.js.map +1 -1
- package/dist/ir/constant-globals.test.js +1 -1
- package/dist/ir/constant-tables.test.js +1 -1
- package/dist/ir/field-values.test.js +1 -1
- package/dist/ir/final-fields.test.js +1 -1
- package/dist/ir/function-references.test.js +10 -1
- package/dist/ir/function-references.test.js.map +1 -1
- package/dist/ir/init-only-globals.test.js +1 -1
- package/dist/ir/initializer-bindings.test.js +1 -1
- package/dist/ir/int32-slots.d.ts +14 -0
- package/dist/ir/int32-slots.js +119 -14
- package/dist/ir/int32-slots.js.map +1 -1
- package/dist/ir/int32-slots.test.js +29 -1
- package/dist/ir/int32-slots.test.js.map +1 -1
- package/dist/ir/integer-loop-facts.d.ts +16 -6
- package/dist/ir/integer-loop-facts.js +143 -38
- package/dist/ir/integer-loop-facts.js.map +1 -1
- package/dist/ir/integer-loops.d.ts +1 -1
- package/dist/ir/integer-loops.js +39 -9
- package/dist/ir/integer-loops.js.map +1 -1
- package/dist/ir/integer-loops.test.js +104 -0
- package/dist/ir/integer-loops.test.js.map +1 -1
- package/dist/ir/integer-ranges.d.ts +3 -0
- package/dist/ir/integer-ranges.js +4 -6
- package/dist/ir/integer-ranges.js.map +1 -1
- package/dist/ir/integer-ranges.test.js +142 -1
- package/dist/ir/integer-ranges.test.js.map +1 -1
- package/dist/ir/intrinsic-signatures.js +6 -0
- package/dist/ir/intrinsic-signatures.js.map +1 -1
- package/dist/ir/ir.d.ts +234 -58
- package/dist/ir/ir.js +123 -12
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/ir.test.js +10 -0
- package/dist/ir/ir.test.js.map +1 -1
- package/dist/ir/jsval.d.ts +8 -0
- package/dist/ir/jsval.js +365 -0
- package/dist/ir/jsval.js.map +1 -0
- package/dist/ir/jsval.test.d.ts +1 -0
- package/dist/ir/jsval.test.js +239 -0
- package/dist/ir/jsval.test.js.map +1 -0
- package/dist/ir/runtime-features.d.ts +150 -33
- package/dist/ir/runtime-features.js +672 -339
- package/dist/ir/runtime-features.js.map +1 -1
- package/dist/ir/runtime-features.test.js +62 -0
- package/dist/ir/runtime-features.test.js.map +1 -1
- package/dist/ir/scalar-records.test.js +1 -1
- package/dist/ir/self-captures.d.ts +33 -0
- package/dist/ir/self-captures.js +245 -0
- package/dist/ir/self-captures.js.map +1 -0
- package/dist/ir/self-captures.test.d.ts +1 -0
- package/dist/ir/self-captures.test.js +135 -0
- package/dist/ir/self-captures.test.js.map +1 -0
- package/dist/ir/serialize.d.ts +1 -1
- package/dist/ir/serialize.js +7 -4
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/tiers.d.ts +26 -0
- package/dist/ir/tiers.js +101 -0
- package/dist/ir/tiers.js.map +1 -0
- package/dist/ir/tiers.test.d.ts +1 -0
- package/dist/ir/tiers.test.js +140 -0
- package/dist/ir/tiers.test.js.map +1 -0
- package/dist/ir/traverse.js +107 -94
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/traverse.test.js +33 -30
- package/dist/ir/traverse.test.js.map +1 -1
- package/dist/ir/unshare.js +65 -3
- package/dist/ir/unshare.js.map +1 -1
- package/dist/ir/unshare.test.js +1 -1
- package/dist/ir/validate.js +220 -71
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +64 -9
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/fence-eval.test.js +1 -1
- package/dist/library/int-infer.test.js +4 -4
- package/dist/library/ir-policy.js +18 -0
- package/dist/library/ir-policy.js.map +1 -1
- package/dist/library/library-cache.d.ts +1 -0
- package/dist/library/library-cache.js.map +1 -1
- package/dist/library/library-cache.test.js +5 -5
- package/dist/library/library-profile.d.ts +4 -4
- package/dist/library/library-profile.js +35 -7
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/prepare.js +13 -1
- package/dist/library/prepare.js.map +1 -1
- package/dist/native/cli.js +5 -0
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.js +2 -2
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/compiler.test.js +2 -2
- package/dist/native/prepare.js +7 -0
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/sanitizer.test.js +12 -0
- package/dist/native/sanitizer.test.js.map +1 -1
- package/dist/native/toolchain.d.ts +2 -0
- package/dist/native/toolchain.js +10 -1
- package/dist/native/toolchain.js.map +1 -1
- package/dist/native/toolchain.test.js +39 -1
- package/dist/native/toolchain.test.js.map +1 -1
- package/dist/startup-cache.d.ts +1 -0
- package/dist/startup-cache.js +1 -0
- package/dist/startup-cache.js.map +1 -1
- package/dist/wasm/base64.d.ts +5 -0
- package/dist/wasm/base64.js +62 -0
- package/dist/wasm/base64.js.map +1 -0
- package/dist/wasm/binary.d.ts +36 -0
- package/dist/wasm/binary.js +1976 -0
- package/dist/wasm/binary.js.map +1 -0
- package/dist/wasm/binary.test.d.ts +1 -0
- package/dist/wasm/binary.test.js +190 -0
- package/dist/wasm/binary.test.js.map +1 -0
- package/dist/wasm/discover.d.ts +38 -0
- package/dist/wasm/discover.js +377 -0
- package/dist/wasm/discover.js.map +1 -0
- package/dist/wasm/discover.test.d.ts +1 -0
- package/dist/wasm/discover.test.js +24 -0
- package/dist/wasm/discover.test.js.map +1 -0
- package/dist/wasm/module.d.ts +151 -0
- package/dist/wasm/module.js +575 -0
- package/dist/wasm/module.js.map +1 -0
- package/dist/wasm/translate.d.ts +48 -0
- package/dist/wasm/translate.js +2129 -0
- package/dist/wasm/translate.js.map +1 -0
- package/dist/wasm/translate.test.d.ts +1 -0
- package/dist/wasm/translate.test.js +207 -0
- package/dist/wasm/translate.test.js.map +1 -0
- package/package.json +21 -20
- package/surface-manifest.json +332 -36
|
@@ -0,0 +1,1964 @@
|
|
|
1
|
+
/* LlEmitter's statement emission: the statement switch, try/catch, switch, loop copies, speculative writes and string self-concatenation. */
|
|
2
|
+
import { adoptingAwaitOf, MAX_BYTES_LOOP_VERSION_DEPTH, } from "./emitter.js";
|
|
3
|
+
import { CAUGHT, F64, STRING, isRefCounted } from "../../ir/ir.js";
|
|
4
|
+
import { emitStringSliceSnapshot } from "./string-slices.js";
|
|
5
|
+
import { canDeferSplitPiece, emitSplitCursor, emitSplitNext, emitSplitScratch, emitSplitSnapshot, emitSplitSpanNext, loadSplitSnapshot, storeSplitSnapshot, stringSplit, } from "./split-loops.js";
|
|
6
|
+
import { emitStackObject, stackObjectFields, stackObjectStruct, } from "./stack-objects.js";
|
|
7
|
+
import { emitStackUnion } from "./stack-unions.js";
|
|
8
|
+
import { emitBorrowedArrayRead, emitLocalArrayRead } from "./local-array-reads.js";
|
|
9
|
+
import { emitStackMapRead } from "./map-read-lifetimes.js";
|
|
10
|
+
import { allocateLocalUnion, storeLocalUnion } from "./local-union-storage.js";
|
|
11
|
+
import { boxAccess, boxNewCall, elemAccess } from "./shapes.js";
|
|
12
|
+
import { dynHoleRead } from "./loop-array-borrows.js";
|
|
13
|
+
import { endsWithJump, matchStringSelfConcat } from "../../ir/analysis.js";
|
|
14
|
+
import { emitDiscardedSplice } from "./expr-containers.js";
|
|
15
|
+
import { InternalCompilerError } from "../../errors.js";
|
|
16
|
+
import { emitDenseArrayGet, emitDenseArrayPop, emitDenseArraySet } from "./dense-array-access.js";
|
|
17
|
+
import { emitBorrowedInput } from "./borrowed-inputs.js";
|
|
18
|
+
import { f64Lit, llvmCommentText, sizeToDouble } from "./common.js";
|
|
19
|
+
import { RESULT_DST_ID, RESULT_ENTRY_PREFIX } from "./record-results.js";
|
|
20
|
+
import { matchIntegerArrayForLoop, matchIntegerBytesForLoop, matchIntegerCountedForLoop, } from "../../ir/integer-loops.js";
|
|
21
|
+
import { emitByteWindowGuard, matchByteWindow } from "./byte-windows.js";
|
|
22
|
+
import { countedDenseShape, emitDenseLoopGuard, matchDenseArrayLoop } from "./dense-array-loops.js";
|
|
23
|
+
import { emitCountedLoopLimit, emitCountedLoopSafety } from "./counted-loops.js";
|
|
24
|
+
import { emitBytesLoopVersionGuard } from "./bytes-loop-versions.js";
|
|
25
|
+
import { mangleLocal } from "../mangle.js";
|
|
26
|
+
import { LlvmUnsupportedError } from "./unsupported.js";
|
|
27
|
+
import { SCALAR_UNION_RESULT } from "./int32-abi.js";
|
|
28
|
+
import { emitLiteralSwitch } from "./switch-dispatch.js";
|
|
29
|
+
import { SPECULATIVE_RANGE, emitSafeIntegerCheck, emitSpeculativeInteger, planSpeculativeLoop, speculativeReads, speculativeWriteTarget, } from "./speculative-integers.js";
|
|
30
|
+
import { emitConcatInputs, emitMixedConcat, numberPart, stringParts, } from "./string-construction.js";
|
|
31
|
+
import { emitStringInputs } from "./string-lifetimes.js";
|
|
32
|
+
export function emitStmtBody(emitter, s) {
|
|
33
|
+
const B = emitter.B;
|
|
34
|
+
emitter.frames.push([]);
|
|
35
|
+
switch (s.kind) {
|
|
36
|
+
case "varDecl": {
|
|
37
|
+
if (s.init && emitter.int32Locals.has(s.localId)) {
|
|
38
|
+
emitter.storeInt32Local(s.localId, emitter.emitExpr(s.init), s.init);
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
const b = emitter.binding(s.localId);
|
|
42
|
+
if (emitter.walkBorrows.has(s.localId) && b.kind === "local") {
|
|
43
|
+
// A borrowed walk pointer: no retain now, no release at scope exit.
|
|
44
|
+
const v = s.init === null ? "null" : emitter.emitReadReceiver(s.init).name;
|
|
45
|
+
B.line(`store ptr ${v}, ptr ${b.slot}`);
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
const slice = emitter.scalarStringSlices.get(s.localId);
|
|
49
|
+
if (slice) {
|
|
50
|
+
const snapshot = emitStringSliceSnapshot(emitter, slice);
|
|
51
|
+
emitter.stringSlices.set(s.localId, snapshot);
|
|
52
|
+
emitter.scopes[emitter.scopes.length - 1].push({ slot: snapshot.source, type: STRING });
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
const split = emitter.privateSplitLocals.get(s.localId);
|
|
56
|
+
if (split) {
|
|
57
|
+
const snapshot = storeSplitSnapshot(emitter, emitSplitSnapshot(emitter, split));
|
|
58
|
+
emitter.storedSplits.set(s.localId, snapshot);
|
|
59
|
+
emitter.scopes[emitter.scopes.length - 1].push({ slot: snapshot.sourceSlot, type: STRING }, { slot: snapshot.separatorSlot, type: STRING });
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
const stackObject = emitter.localStackObjects.get(s.localId);
|
|
63
|
+
if (stackObject) {
|
|
64
|
+
const value = emitStackObject(emitter, stackObject, (fields) => emitter.ownScopeFields(fields));
|
|
65
|
+
B.line(`store ptr ${value.name}, ptr ${b.slot}`);
|
|
66
|
+
break;
|
|
67
|
+
}
|
|
68
|
+
if (s.init && emitter.reassignedStackObjects.has(s.localId)) {
|
|
69
|
+
const slot = emitter.stackObjectSlot(s.localId, s.init.type);
|
|
70
|
+
emitStackObject(emitter, s.init, (fields) => emitter.ownScopeFields(fields), slot);
|
|
71
|
+
B.line(`store ptr ${slot}, ptr ${b.slot}`);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
const localUnion = emitter.localStackUnions.get(s.localId);
|
|
75
|
+
if (localUnion) {
|
|
76
|
+
const union = emitStackUnion(emitter, localUnion);
|
|
77
|
+
B.line(`store ptr ${union.value.name}, ptr ${b.slot}`);
|
|
78
|
+
if (union.payload) {
|
|
79
|
+
emitter.toFrame(union.payload);
|
|
80
|
+
emitter.scopes[emitter.scopes.length - 1].push({
|
|
81
|
+
slot: union.payloadSlot,
|
|
82
|
+
type: union.payload.type,
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
const localRead = emitter.localArrayReads.get(s.localId);
|
|
88
|
+
if (localRead) {
|
|
89
|
+
const owner = emitLocalArrayRead(emitter, !localRead.borrow && emitter.unwrittenLocalArrayRead(s, localRead)
|
|
90
|
+
? { ...localRead, borrow: true }
|
|
91
|
+
: localRead, b.slot);
|
|
92
|
+
if (owner)
|
|
93
|
+
emitter.scopes[emitter.scopes.length - 1].push(owner);
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
const mapRead = emitter.mapReadLifetimes.locals.get(s.localId);
|
|
97
|
+
if (mapRead) {
|
|
98
|
+
const result = emitStackMapRead(emitter, mapRead);
|
|
99
|
+
B.line(`store ptr ${result.value.name}, ptr ${b.slot}`);
|
|
100
|
+
if (result.owner)
|
|
101
|
+
emitter.scopes[emitter.scopes.length - 1].push(result.owner);
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
const localStorage = emitter.localUnionStorageProofs.get(s.localId);
|
|
105
|
+
if (localStorage && s.init) {
|
|
106
|
+
const storage = allocateLocalUnion(emitter, localStorage);
|
|
107
|
+
emitter.localUnionStorage.set(s.localId, storage);
|
|
108
|
+
storeLocalUnion(emitter, storage, s.init);
|
|
109
|
+
B.line(`store ptr ${storage.box}, ptr ${b.slot}`);
|
|
110
|
+
if (storage.owner && storage.ownerType)
|
|
111
|
+
emitter.scopes[emitter.scopes.length - 1].push({
|
|
112
|
+
slot: storage.owner,
|
|
113
|
+
type: storage.ownerType,
|
|
114
|
+
});
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
if (b.kind === "boxed") {
|
|
118
|
+
const stack = emitter.stackCaptures.emit(emitter, s.localId, b.type);
|
|
119
|
+
if (stack) {
|
|
120
|
+
B.line(`store ptr ${stack.box}, ptr ${b.slot}`);
|
|
121
|
+
if (stack.owner)
|
|
122
|
+
emitter.scopes[emitter.scopes.length - 1].push(stack.owner);
|
|
123
|
+
if (s.init) {
|
|
124
|
+
const value = emitter.emitExpr(s.init);
|
|
125
|
+
if (isRefCounted(value.type))
|
|
126
|
+
emitter.toFrame(value);
|
|
127
|
+
emitter.boxSet(stack.box, b.type, value.name);
|
|
128
|
+
}
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
// Box FIRST, then evaluate the initializer: a named function
|
|
132
|
+
// expression's closure captures this box during init evaluation.
|
|
133
|
+
// A SCALAR TDZ box rides an ARR-kind box: the value lives in a
|
|
134
|
+
// one-element array cell, so the empty (NULL) slot stays the
|
|
135
|
+
// not-yet-initialized sentinel — a raw scalar slot has no spare
|
|
136
|
+
// bit pattern to spend on it (stmts.ts's varDecl).
|
|
137
|
+
const boxNew = b.local.tdz === true && boxAccess(b.type) !== "ref"
|
|
138
|
+
? (emitter.declare(`declare ptr @scr_box_new(i32)`), `call ptr @scr_box_new(i32 3)`)
|
|
139
|
+
: boxNewCall(emitter.shapeHost, b.type);
|
|
140
|
+
const box = B.tmp();
|
|
141
|
+
B.line(`${box} = ${boxNew} ; let ${b.local.name} (boxed)`);
|
|
142
|
+
B.line(`store ptr ${box}, ptr ${b.slot}`);
|
|
143
|
+
emitter.scopes[emitter.scopes.length - 1].push({
|
|
144
|
+
slot: b.slot,
|
|
145
|
+
type: b.type,
|
|
146
|
+
boxed: true,
|
|
147
|
+
});
|
|
148
|
+
if (s.init === null) {
|
|
149
|
+
// An empty TDZ box whose payload can legitimately be NULL
|
|
150
|
+
// starts at its distinct sentinel (tdzEmptySentinel).
|
|
151
|
+
const sentinel = b.local.tdz === true ? emitter.tdzEmptySentinel(b.type) : null;
|
|
152
|
+
if (sentinel !== null)
|
|
153
|
+
B.line(`store ptr ${sentinel}, ptr ${emitter.boxSlot(box)}`);
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
const v = emitter.emitExpr(s.init);
|
|
157
|
+
if (isRefCounted(v.type))
|
|
158
|
+
emitter.toHeap(v); // the box takes ownership
|
|
159
|
+
if (b.local.tdz === true && boxAccess(b.type) !== "ref") {
|
|
160
|
+
emitter.tdzScalarInit(box, b.type, v.name);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
emitter.boxSet(box, b.type, v.name);
|
|
164
|
+
}
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
if (s.init === null) {
|
|
168
|
+
// Declared, uninitialized (`let x: number;`): reset the slot —
|
|
169
|
+
// inside a loop the previous iteration's scope exit released the
|
|
170
|
+
// old value and left a stale pointer (NULL-tolerant releases).
|
|
171
|
+
if (isRefCounted(b.type)) {
|
|
172
|
+
B.line(`store ptr null, ptr ${b.slot}`);
|
|
173
|
+
emitter.scopes[emitter.scopes.length - 1].push({ slot: b.slot, type: b.type });
|
|
174
|
+
}
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
if (emitter.loopArrayBorrows.has(s) && s.init.kind === "arrayGet") {
|
|
178
|
+
emitBorrowedArrayRead(emitter, s.init, b.slot);
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
const holeRead = emitter.loopArrayBorrows.has(s) ? dynHoleRead(s.init) : null;
|
|
182
|
+
if (holeRead && s.init.kind === "ternary") {
|
|
183
|
+
// A hole reads as the immortal undefined value, which needs no owner.
|
|
184
|
+
const present = emitter.emitExpr(s.init.cond);
|
|
185
|
+
const filled = B.newLabel("borrow.hole.filled"), missing = B.newLabel("borrow.hole.missing"), done = B.newLabel("borrow.hole.done");
|
|
186
|
+
B.condBr(present.name, filled, missing);
|
|
187
|
+
B.startBlock(filled);
|
|
188
|
+
emitBorrowedArrayRead(emitter, holeRead, b.slot);
|
|
189
|
+
B.br(done);
|
|
190
|
+
B.startBlock(missing);
|
|
191
|
+
emitter.declare("declare ptr @scr_dyn_undefined()");
|
|
192
|
+
const undef = B.tmp();
|
|
193
|
+
B.line(`${undef} = call ptr @scr_dyn_undefined()`);
|
|
194
|
+
B.line(`store ptr ${undef}, ptr ${b.slot}`);
|
|
195
|
+
B.br(done);
|
|
196
|
+
B.startBlock(done);
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
// A stable lexical alias cannot outlive its unchanged local owner.
|
|
200
|
+
// Whole-value uses still retain their own copies, so returning or
|
|
201
|
+
// storing the alias preserves the ordinary heap representation.
|
|
202
|
+
// Boxed captures, reassigned sources and projections need ownership.
|
|
203
|
+
if (b.kind === "local" &&
|
|
204
|
+
b.local &&
|
|
205
|
+
isRefCounted(b.type) &&
|
|
206
|
+
emitter.stableCallBindings.has(s.localId) &&
|
|
207
|
+
(emitter.canBorrowCallArgument(s.init) || emitter.unwrittenAlias(s))) {
|
|
208
|
+
const v = emitter.emitReadReceiver(s.init);
|
|
209
|
+
B.line(`store ptr ${v.name}, ptr ${b.slot}`);
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
const v = emitter.emitExpr(s.init);
|
|
213
|
+
if (b.kind === "global")
|
|
214
|
+
emitter.toHeap(v);
|
|
215
|
+
else
|
|
216
|
+
emitter.toFrame(v);
|
|
217
|
+
B.line(`store ${emitter.llType(b.type)} ${v.name}, ptr ${b.slot}`);
|
|
218
|
+
emitter.storeIntegerView(s.localId, v, s.init);
|
|
219
|
+
if (isRefCounted(b.type)) {
|
|
220
|
+
emitter.scopes[emitter.scopes.length - 1].push({ slot: b.slot, type: b.type });
|
|
221
|
+
emitter.noteLastUseMove(s, b);
|
|
222
|
+
}
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
case "assign": {
|
|
226
|
+
if (emitter.int32Locals.has(s.localId)) {
|
|
227
|
+
emitter.storeInt32Local(s.localId, emitter.emitExpr(s.value), s.value);
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
const owner = emitter.reboundOwnerSlots.get(s.localId);
|
|
231
|
+
if (owner !== undefined && !emitter.walkBorrows.has(s.localId)) {
|
|
232
|
+
// A rebound borrowed parameter: the new value moves into the owner
|
|
233
|
+
// slot, replacing (and releasing) the previous owned value. This
|
|
234
|
+
// precedes the in-place string append, which would release the
|
|
235
|
+
// caller's borrow.
|
|
236
|
+
const param = emitter.binding(s.localId);
|
|
237
|
+
const slot = param.slot;
|
|
238
|
+
const v = emitter.emitExpr(s.value);
|
|
239
|
+
emitter.toFrame(v);
|
|
240
|
+
const old = B.tmp();
|
|
241
|
+
B.line(`${old} = load ptr, ptr ${owner}`);
|
|
242
|
+
emitter.releaseFrame(old, param.type);
|
|
243
|
+
B.line(`store ptr ${v.name}, ptr ${slot}`);
|
|
244
|
+
B.line(`store ptr ${v.name}, ptr ${owner}`);
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
if (emitter.reassignedStackObjects.has(s.localId)) {
|
|
248
|
+
// The new value may read the old one: build it apart (its
|
|
249
|
+
// reference fields owned by this statement until it completes),
|
|
250
|
+
// then copy it over the binding's slot. The binding takes over the
|
|
251
|
+
// new fields; the old ones are released after the slot no longer
|
|
252
|
+
// holds them.
|
|
253
|
+
const struct = stackObjectStruct(s.value.type);
|
|
254
|
+
let owned = [];
|
|
255
|
+
const value = emitStackObject(emitter, s.value, (fields) => {
|
|
256
|
+
owned = fields;
|
|
257
|
+
for (const field of fields)
|
|
258
|
+
emitter.ownSlot(field.ptr, field.type);
|
|
259
|
+
});
|
|
260
|
+
const target = emitter.stackObjectSlot(s.localId, s.value.type);
|
|
261
|
+
const old = stackObjectFields(emitter, s.value.type, target).map((field) => {
|
|
262
|
+
const t = B.tmp();
|
|
263
|
+
B.line(`${t} = load ptr, ptr ${field.ptr}`);
|
|
264
|
+
return { name: t, type: field.type };
|
|
265
|
+
});
|
|
266
|
+
const bits = B.tmp();
|
|
267
|
+
B.line(`${bits} = load ${struct}, ptr ${value.name}`);
|
|
268
|
+
B.line(`store ${struct} ${bits}, ptr ${target}`);
|
|
269
|
+
emitter.disownSlots(owned);
|
|
270
|
+
for (const field of old)
|
|
271
|
+
emitter.releaseFrame(field.name, field.type);
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
const localStorage = emitter.localUnionStorage.get(s.localId);
|
|
275
|
+
if (localStorage) {
|
|
276
|
+
storeLocalUnion(emitter, localStorage, s.value);
|
|
277
|
+
break;
|
|
278
|
+
}
|
|
279
|
+
const self = matchStringSelfConcat(s.localId, s.value);
|
|
280
|
+
if (self) {
|
|
281
|
+
emitter.emitStringSelfConcatAssign(s.localId, self.left, self.suffix, false);
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
const b = emitter.binding(s.localId);
|
|
285
|
+
if (emitter.walkBorrows.has(s.localId) && b.kind === "local") {
|
|
286
|
+
// Rebinding a borrowed walk pointer releases nothing.
|
|
287
|
+
B.line(`store ptr ${emitter.emitReadReceiver(s.value).name}, ptr ${b.slot}`);
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
const v = emitter.emitExpr(s.value);
|
|
291
|
+
if (b.kind === "global" && !s.initializes)
|
|
292
|
+
emitter.checkGlobalTdz(s.localId);
|
|
293
|
+
if (b.kind === "boxed") {
|
|
294
|
+
emitter.writeBindingBox(emitter.loadBox(b.slot), b.local, v.name, s.initializes);
|
|
295
|
+
// The RHS remains frame-owned until a possible TDZ throw passes.
|
|
296
|
+
if (isRefCounted(v.type))
|
|
297
|
+
emitter.toHeap(v);
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
if (b.kind === "global")
|
|
301
|
+
emitter.toHeap(v);
|
|
302
|
+
else
|
|
303
|
+
emitter.toFrame(v);
|
|
304
|
+
if (isRefCounted(b.type)) {
|
|
305
|
+
const old = B.tmp();
|
|
306
|
+
B.line(`${old} = load ptr, ptr ${b.slot}`);
|
|
307
|
+
if (b.kind === "global")
|
|
308
|
+
emitter.releaseHeap(old, b.type);
|
|
309
|
+
else
|
|
310
|
+
emitter.releaseFrame(old, b.type);
|
|
311
|
+
}
|
|
312
|
+
B.line(`store ${emitter.llType(b.type)} ${v.name}, ptr ${b.slot}`);
|
|
313
|
+
emitter.storeIntegerView(s.localId, v, s.value);
|
|
314
|
+
if (b.kind === "global" && emitter.immortalGlobals.has(s.localId)) {
|
|
315
|
+
// An Immutable module constant (contracts/check.ts proved it is
|
|
316
|
+
// fresh, publishable and never written): its graph becomes
|
|
317
|
+
// immortal, so reads skip reference counting and the collector
|
|
318
|
+
// never visits it.
|
|
319
|
+
const lines = emitter.publishWalkers.emitPublish(v.name, v.type, s.loc);
|
|
320
|
+
for (const line of lines)
|
|
321
|
+
B.line(line.trimStart());
|
|
322
|
+
// Reads of this global skip retains from here on, which is only
|
|
323
|
+
// sound once the graph really is immortal. Node.js never fails
|
|
324
|
+
// here, so a refusal means the contract proof was wrong: stop
|
|
325
|
+
// rather than keep running with a mortal graph read as immortal.
|
|
326
|
+
if (lines.length > 0) {
|
|
327
|
+
emitter.declare(`declare zeroext i1 @scr_exc_pending()`);
|
|
328
|
+
emitter.declare(`declare void @scr_trap(ptr)`);
|
|
329
|
+
const refused = B.tmp();
|
|
330
|
+
B.line(`${refused} = call zeroext i1 @scr_exc_pending()`);
|
|
331
|
+
const stop = B.newLabel("immutable.refused");
|
|
332
|
+
const done = B.newLabel("immutable.published");
|
|
333
|
+
B.condBr(refused, stop, done);
|
|
334
|
+
B.startBlock(stop);
|
|
335
|
+
B.line(`call void @scr_trap(ptr ${emitter.cstr("scriptc: internal error: an Immutable value could not be published\n")})`);
|
|
336
|
+
B.terminate("unreachable");
|
|
337
|
+
B.startBlock(done);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
case "exprStmt":
|
|
343
|
+
// A statement-position splice never observes its removed elements.
|
|
344
|
+
if (!emitDiscardedSplice(emitter, s.expr))
|
|
345
|
+
emitter.emitDiscarded(s.expr);
|
|
346
|
+
break;
|
|
347
|
+
case "arraySet": {
|
|
348
|
+
// Evaluation order matches JS: array, index, then value. Ownership
|
|
349
|
+
// of a refcounted value moves into the array (the runtime releases
|
|
350
|
+
// the replaced element itself). A local receiver that the index and
|
|
351
|
+
// value cannot rebind is read in place, as for field stores; the
|
|
352
|
+
// released element cannot reach that binding.
|
|
353
|
+
if (emitter.emitArraySelfConcat(s))
|
|
354
|
+
break;
|
|
355
|
+
const arr = emitter.emitStableReceiver(s.arr, [s.index, s.value]);
|
|
356
|
+
const idx = emitter.emitExpr(s.index);
|
|
357
|
+
const v = emitter.emitExpr(s.value);
|
|
358
|
+
if (s.arr.type.kind !== "array")
|
|
359
|
+
throw new InternalCompilerError("llvm emitter bug: arraySet on non-array");
|
|
360
|
+
const acc = elemAccess(s.arr.type.elem);
|
|
361
|
+
emitter.emitPublishedArrayGuard(arr.name, s.arr.type, 0, idx.name);
|
|
362
|
+
if (acc === "ref")
|
|
363
|
+
emitter.toHeap(v);
|
|
364
|
+
emitDenseArraySet(emitter, arr.name, idx, s.index, acc, s.arr.type.elem, v.name, emitter.provenDenseIndex(s.arr, s.index));
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
367
|
+
case "arraySetLength": {
|
|
368
|
+
// Pop's `length = 0` store on an empty array only matters when the
|
|
369
|
+
// array can be frozen (published); its operand is a local.
|
|
370
|
+
if (s.pop === true &&
|
|
371
|
+
s.length.kind === "numLit" &&
|
|
372
|
+
s.length.value === 0 &&
|
|
373
|
+
emitter.publishedTypes?.containerGuarded(s.arr.type) !== true)
|
|
374
|
+
break;
|
|
375
|
+
const arr = emitBorrowedInput(emitter, s.arr);
|
|
376
|
+
const length = emitter.emitExpr(s.length);
|
|
377
|
+
if (s.arr.type.kind !== "array")
|
|
378
|
+
throw new InternalCompilerError("llvm emitter bug: arraySetLength on non-array");
|
|
379
|
+
emitter.emitPublishedArrayGuard(arr.name, s.arr.type, s.pop === true ? 2 : 3);
|
|
380
|
+
emitter.declare(`declare void @scr_arr_set_len(ptr, double)`);
|
|
381
|
+
// Assigning the current length (a reused work array reset to where
|
|
382
|
+
// it already is) changes nothing: the runtime's validation accepts
|
|
383
|
+
// exactly the value equal to the length (-0 included, NaN never),
|
|
384
|
+
// and no element is released. Everything else keeps the call.
|
|
385
|
+
const lenPtr = B.tmp(), len = B.tmp(), lenNumber = B.tmp(), same = B.tmp();
|
|
386
|
+
const resize = B.newLabel("arr.len.set"), done = B.newLabel("arr.len.done");
|
|
387
|
+
B.line(`${lenPtr} = getelementptr inbounds %ScrArr, ptr ${arr.name}, i32 0, i32 1`);
|
|
388
|
+
emitter.markMemoryPointer(lenPtr, "array:header");
|
|
389
|
+
B.line(`${len} = load ${emitter.sizeType}, ptr ${lenPtr}${emitter.fieldAliasAttachment(lenPtr)}${emitter.arrayLengthRange}`);
|
|
390
|
+
B.line(`${lenNumber} = ${sizeToDouble(emitter.sizeType)} ${emitter.sizeType} ${len} to double`);
|
|
391
|
+
B.line(`${same} = fcmp oeq double ${length.name}, ${lenNumber}`);
|
|
392
|
+
B.condBr(same, done, resize);
|
|
393
|
+
B.startBlock(resize);
|
|
394
|
+
if (s.pop === true) {
|
|
395
|
+
// A discarded pop's `length - 1` on a packed array removes the
|
|
396
|
+
// last element inline, then releases it.
|
|
397
|
+
const call = B.newLabel("arr.len.call"), pop = B.newLabel("arr.len.pop");
|
|
398
|
+
const lastNumber = B.tmp(), dropsLast = B.tmp();
|
|
399
|
+
B.line(`${lastNumber} = fsub double ${lenNumber}, 1.0`);
|
|
400
|
+
B.line(`${dropsLast} = fcmp oeq double ${length.name}, ${lastNumber}`);
|
|
401
|
+
B.condBr(dropsLast, pop, call);
|
|
402
|
+
B.startBlock(pop);
|
|
403
|
+
const elem = s.arr.type.elem;
|
|
404
|
+
const acc = elemAccess(elem);
|
|
405
|
+
const raw = emitDenseArrayPop(emitter, arr.name, acc, call, call);
|
|
406
|
+
if (acc === "ref" && isRefCounted(elem)) {
|
|
407
|
+
const old = B.tmp();
|
|
408
|
+
B.line(`${old} = inttoptr i64 ${raw} to ptr`);
|
|
409
|
+
emitter.releaseHeap(old, elem);
|
|
410
|
+
}
|
|
411
|
+
B.br(done);
|
|
412
|
+
B.startBlock(call);
|
|
413
|
+
}
|
|
414
|
+
B.line(`call void @scr_arr_set_len(ptr ${arr.name}, double ${length.name})`);
|
|
415
|
+
emitter.emitPendingCheck();
|
|
416
|
+
B.br(done);
|
|
417
|
+
B.startBlock(done);
|
|
418
|
+
break;
|
|
419
|
+
}
|
|
420
|
+
case "arraySetUndefined":
|
|
421
|
+
case "arrayDelete": {
|
|
422
|
+
const arr = emitBorrowedInput(emitter, s.arr);
|
|
423
|
+
const idx = emitter.emitExpr(s.index);
|
|
424
|
+
if (s.arr.type.kind !== "array")
|
|
425
|
+
throw new InternalCompilerError(`llvm emitter bug: ${s.kind} on non-array`);
|
|
426
|
+
emitter.emitPublishedArrayGuard(arr.name, s.arr.type, s.kind === "arrayDelete" ? 5 : 0, idx.name);
|
|
427
|
+
const fn = s.kind === "arraySetUndefined" ? "scr_arr_set_undefined" : "scr_arr_delete";
|
|
428
|
+
emitter.declare(`declare ${s.kind === "arrayDelete" ? "zeroext i1" : "void"} @${fn}(ptr, double)`);
|
|
429
|
+
if (s.kind === "arrayDelete")
|
|
430
|
+
B.line(`call zeroext i1 @${fn}(ptr ${arr.name}, double ${idx.name})`);
|
|
431
|
+
else
|
|
432
|
+
B.line(`call void @${fn}(ptr ${arr.name}, double ${idx.name})`);
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
case "bytesSet": {
|
|
436
|
+
// Typed-array element write: same evaluation order as arraySet;
|
|
437
|
+
// the value is a scalar (the kind-specific inline path coerces
|
|
438
|
+
// JS-exactly), so no ownership moves. Invalid writes are ignored.
|
|
439
|
+
// IrBytesElem is static, so never rediscover it through the
|
|
440
|
+
// generic runtime switch in a hot loop.
|
|
441
|
+
const arr = emitter.emitStableReceiver(s.arr, [s.index, s.value]);
|
|
442
|
+
const idx = emitter.emitExpr(s.index);
|
|
443
|
+
const v = emitter.emitExpr(s.value);
|
|
444
|
+
if (s.arr.type.kind !== "bytes")
|
|
445
|
+
throw new InternalCompilerError("llvm emitter bug: bytesSet on non-bytes");
|
|
446
|
+
emitter.emitBytesSet(s.arr.type.elem, arr.name, idx, v, s.index, s.value, emitter.bytesBounds.has(s));
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
case "fieldSet":
|
|
450
|
+
case "recordSet": {
|
|
451
|
+
// Evaluation order: obj, then value. New value moved in; the old
|
|
452
|
+
// value is released AFTER the field is overwritten (unlink-then-
|
|
453
|
+
// release — a release can trigger a cycle collection, which must
|
|
454
|
+
// never see a heap edge whose count was already given up).
|
|
455
|
+
// Classes and records share the struct layout, so one emission.
|
|
456
|
+
const nullable = s.kind === "fieldSet" ? emitter.nullableFields.get(s.className, s.field) : null;
|
|
457
|
+
if (nullable && s.kind === "fieldSet") {
|
|
458
|
+
const obj = emitter.emitStableReceiver(s.obj, [s.value]);
|
|
459
|
+
// (The guard precedes the value here: the nullable store
|
|
460
|
+
// evaluates it itself.)
|
|
461
|
+
emitter.emitStoreGuard(obj.name, s);
|
|
462
|
+
emitter.emitNullableFieldStore(obj.name, s.className, s.field, nullable, s.value);
|
|
463
|
+
break;
|
|
464
|
+
}
|
|
465
|
+
if (s.kind === "fieldSet" && emitter.int32Slots.isField(s.className, s.field)) {
|
|
466
|
+
const obj = emitter.emitStableReceiver(s.obj, [s.value]);
|
|
467
|
+
const v = emitter.emitExpr(s.value);
|
|
468
|
+
emitter.emitStoreGuard(obj.name, s);
|
|
469
|
+
const { ptr } = emitter.classFieldPtr(obj.name, s.className, s.field);
|
|
470
|
+
emitter.storeInt32Field(ptr, v, s.value);
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
473
|
+
if (emitter.emitFieldSelfConcat(s))
|
|
474
|
+
break;
|
|
475
|
+
const obj = emitter.emitStableReceiver(s.obj, [s.value]);
|
|
476
|
+
const v = emitter.emitFieldValue(s.value, s.kind === "recordSet"
|
|
477
|
+
? emitter.recordFieldInline(s.shapeId, s.field)
|
|
478
|
+
: emitter.inlineUnions.classField(s.className, s.field));
|
|
479
|
+
if (s.kind === "fieldSet")
|
|
480
|
+
emitter.emitStoreGuard(obj.name, s);
|
|
481
|
+
else if (emitter.publishedTypes?.recordGuarded(s.shapeId) === true)
|
|
482
|
+
emitter.emitPublishedFieldGuard(obj.name, null, s.field);
|
|
483
|
+
const { ptr, type, inline } = s.kind === "fieldSet"
|
|
484
|
+
? emitter.classFieldPtr(obj.name, s.className, s.field)
|
|
485
|
+
: emitter.recordFieldPtr(obj.name, s.shapeId, s.field);
|
|
486
|
+
// A result-slot entry fills zeroed caller storage, each field once.
|
|
487
|
+
if (s.kind === "recordSet" &&
|
|
488
|
+
s.obj.kind === "varRef" &&
|
|
489
|
+
s.obj.localId === RESULT_DST_ID &&
|
|
490
|
+
emitter.currentFunctionName.startsWith(RESULT_ENTRY_PREFIX))
|
|
491
|
+
emitter.initField(ptr, type, inline, v);
|
|
492
|
+
else
|
|
493
|
+
emitter.replaceField(ptr, type, inline, v);
|
|
494
|
+
if (s.kind === "fieldSet" &&
|
|
495
|
+
s.field === "name" &&
|
|
496
|
+
emitter.classMeta.get(s.className)?.root.def.name === "%Error") {
|
|
497
|
+
const present = emitter.classFieldPtr(obj.name, s.className, "%namePresent").ptr;
|
|
498
|
+
const enumerable = emitter.classFieldPtr(obj.name, s.className, "%nameEnumerable").ptr;
|
|
499
|
+
const wasPresent = B.tmp(), wasEnumerable = B.tmp(), isPresent = B.tmp(), nextEnumerable = B.tmp();
|
|
500
|
+
B.line(`${wasPresent} = load i8, ptr ${present}`);
|
|
501
|
+
B.line(`${wasEnumerable} = load i8, ptr ${enumerable}`);
|
|
502
|
+
B.line(`${isPresent} = icmp ne i8 ${wasPresent}, 0`);
|
|
503
|
+
B.line(`${nextEnumerable} = select i1 ${isPresent}, i8 ${wasEnumerable}, i8 1`);
|
|
504
|
+
B.line(`store i8 1, ptr ${present}`);
|
|
505
|
+
B.line(`store i8 ${nextEnumerable}, ptr ${enumerable}`);
|
|
506
|
+
}
|
|
507
|
+
break;
|
|
508
|
+
}
|
|
509
|
+
case "recordKeyDelete": {
|
|
510
|
+
// `delete obj[k]` on a pure index-signature shape: a Map delete on
|
|
511
|
+
// the overflow (key and value released; absent keys no-op).
|
|
512
|
+
const obj = emitter.emitExpr(s.obj);
|
|
513
|
+
const key = emitter.emitExpr(s.key);
|
|
514
|
+
if (emitter.publishedTypes?.recordGuarded(s.shapeId) === true) {
|
|
515
|
+
// Node: "Cannot delete property 'k' of #<Object>" (key known at
|
|
516
|
+
// run time only; the guard reports the frozen record generically).
|
|
517
|
+
emitter.emitPublishedFieldGuard(obj.name, null, "[key]");
|
|
518
|
+
}
|
|
519
|
+
const ovf = emitter.recordOvfPtr(obj.name, s.shapeId);
|
|
520
|
+
emitter.declare(`declare zeroext i1 @scr_map_delete_str(ptr, ptr)`);
|
|
521
|
+
const t = B.tmp();
|
|
522
|
+
B.line(`${t} = call zeroext i1 @scr_map_delete_str(ptr ${ovf}, ptr ${key.name})`);
|
|
523
|
+
break;
|
|
524
|
+
}
|
|
525
|
+
case "recordKeySet": {
|
|
526
|
+
// Dynamic-keyed record write (the C per-shape helper, inline):
|
|
527
|
+
// declared keys write through (same-typed — dyn-valued shapes,
|
|
528
|
+
// whose writes validate and can throw, stay refused), undeclared
|
|
529
|
+
// keys insert/replace in the overflow map. Evaluation order: obj,
|
|
530
|
+
// key, value; the write OWNS the value (+1 moves in).
|
|
531
|
+
const obj = emitter.emitExpr(s.obj);
|
|
532
|
+
const key = emitter.emitExpr(s.key);
|
|
533
|
+
const v = emitter.emitExpr(s.value);
|
|
534
|
+
if (emitter.publishedTypes?.recordGuarded(s.shapeId) === true)
|
|
535
|
+
emitter.emitPublishedFieldGuard(obj.name, null, "[key]");
|
|
536
|
+
if (isRefCounted(v.type))
|
|
537
|
+
emitter.toHeap(v);
|
|
538
|
+
const shape = emitter.recordShape(s.shapeId);
|
|
539
|
+
// Signature-free shapes dispatch over their (one-typed) declared
|
|
540
|
+
// fields and TRAP on a miss (scr_record_key_miss — JS would add
|
|
541
|
+
// the property, which a monomorphic struct cannot); overflow
|
|
542
|
+
// shapes keep the map insert tail.
|
|
543
|
+
const iv = shape.indexValue ?? shape.fields[0]?.type;
|
|
544
|
+
if (!iv)
|
|
545
|
+
throw new InternalCompilerError(`llvm emitter bug: keyed write on field-free non-overflow shape ${s.shapeId}`);
|
|
546
|
+
const vAcc = iv.kind === "f64" ? "f64" : iv.kind === "bool" ? "bool" : "ref";
|
|
547
|
+
if (s.overflowOnly === true) {
|
|
548
|
+
// A LITERAL key naming no declared field: a plain overflow
|
|
549
|
+
// insert — no field chain.
|
|
550
|
+
const ovf = emitter.recordOvfPtr(obj.name, s.shapeId);
|
|
551
|
+
emitter.mapSet(ovf, "str", vAcc, key.name, v.name);
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
554
|
+
const join = B.newLabel("rks.j");
|
|
555
|
+
if (iv.kind === "dyn" && shape.indexValue) {
|
|
556
|
+
// A dyn-valued shape (the C recordKeySetHelper's dyn arm,
|
|
557
|
+
// inline): declared keys VALIDATE the dyn value against the
|
|
558
|
+
// field's type first (dynCheck — a mismatched write throws the
|
|
559
|
+
// catchable TypeError and leaves the field untouched; JS would
|
|
560
|
+
// store anything, the documented divergence); undeclared keys
|
|
561
|
+
// insert the dyn value into the overflow map as-is.
|
|
562
|
+
emitter.declare(`declare void @scr_dyn_release(ptr)`);
|
|
563
|
+
for (const f of shape.fields) {
|
|
564
|
+
const hit = B.tmp();
|
|
565
|
+
B.line(`${hit} = call zeroext i1 ${emitter.literalEquals(f.name)}(ptr ${key.name}) ; ${llvmCommentText(f.name)}`);
|
|
566
|
+
const lh = B.newLabel("rks.h");
|
|
567
|
+
const ln = B.newLabel("rks.n");
|
|
568
|
+
B.condBr(hit, lh, ln);
|
|
569
|
+
B.startBlock(lh);
|
|
570
|
+
const pathSlot = B.slot();
|
|
571
|
+
B.entryAllocas.push(`${pathSlot} = alloca %ScrDynPath`);
|
|
572
|
+
const pp = B.tmp();
|
|
573
|
+
const kp = B.tmp();
|
|
574
|
+
const ip = B.tmp();
|
|
575
|
+
B.line(`${pp} = getelementptr inbounds %ScrDynPath, ptr ${pathSlot}, i64 0, i32 0`);
|
|
576
|
+
B.line(`store ptr null, ptr ${pp}`);
|
|
577
|
+
B.line(`${kp} = getelementptr inbounds %ScrDynPath, ptr ${pathSlot}, i64 0, i32 1`);
|
|
578
|
+
B.line(`store ptr ${emitter.cstr(f.name)}, ptr ${kp}`);
|
|
579
|
+
B.line(`${ip} = getelementptr inbounds %ScrDynPath, ptr ${pathSlot}, i64 0, i32 2`);
|
|
580
|
+
B.line(`store ${emitter.sizeType} 0, ptr ${ip}`);
|
|
581
|
+
const helper = emitter.dyn.dynCheckHelper(f.type);
|
|
582
|
+
const fty = emitter.llType(f.type);
|
|
583
|
+
const nv = B.tmp();
|
|
584
|
+
B.line(`${nv} = call ${fty === "i1" ? "zeroext i1" : fty} @${helper}(ptr ${v.name}, ptr ${pathSlot})`);
|
|
585
|
+
B.line(`call void @scr_dyn_release(ptr ${v.name})`);
|
|
586
|
+
// Mismatched write: TypeError pending, field untouched — the
|
|
587
|
+
// statement-level check below unwinds.
|
|
588
|
+
const pend = B.tmp();
|
|
589
|
+
for (const line of emitter.pendingTestLines(pend))
|
|
590
|
+
B.line(line.trimStart());
|
|
591
|
+
const lw = B.newLabel("rks.w");
|
|
592
|
+
B.condBr(pend, join, lw);
|
|
593
|
+
B.startBlock(lw);
|
|
594
|
+
const { ptr, type, inline } = emitter.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
595
|
+
if (inline) {
|
|
596
|
+
// The slot copies the checked value's bits; nv is released below.
|
|
597
|
+
emitter.storeField(ptr, type, nv, true);
|
|
598
|
+
emitter.releaseFrame(nv, type);
|
|
599
|
+
}
|
|
600
|
+
else if (isRefCounted(type)) {
|
|
601
|
+
const old = B.tmp();
|
|
602
|
+
B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
603
|
+
emitter.storeField(ptr, type, nv, false);
|
|
604
|
+
emitter.releaseHeap(old, type);
|
|
605
|
+
}
|
|
606
|
+
else {
|
|
607
|
+
emitter.storeField(ptr, type, nv, false);
|
|
608
|
+
}
|
|
609
|
+
B.br(join);
|
|
610
|
+
B.startBlock(ln);
|
|
611
|
+
}
|
|
612
|
+
const ovf = emitter.recordOvfPtr(obj.name, s.shapeId);
|
|
613
|
+
emitter.mapSet(ovf, "str", vAcc, key.name, v.name);
|
|
614
|
+
B.br(join);
|
|
615
|
+
B.startBlock(join);
|
|
616
|
+
// MAY THROW exactly when a dyn value can validate against a
|
|
617
|
+
// declared field (stmts.ts's condition).
|
|
618
|
+
if (shape.fields.length > 0)
|
|
619
|
+
emitter.emitPendingCheck();
|
|
620
|
+
break;
|
|
621
|
+
}
|
|
622
|
+
for (const f of shape.fields) {
|
|
623
|
+
// typeEquals(f.type, iv) — the frontend fences everything else.
|
|
624
|
+
const hit = B.tmp();
|
|
625
|
+
B.line(`${hit} = call zeroext i1 ${emitter.literalEquals(f.name)}(ptr ${key.name}) ; ${llvmCommentText(f.name)}`);
|
|
626
|
+
const lh = B.newLabel("rks.h");
|
|
627
|
+
const ln = B.newLabel("rks.n");
|
|
628
|
+
B.condBr(hit, lh, ln);
|
|
629
|
+
B.startBlock(lh);
|
|
630
|
+
const { ptr, type, inline } = emitter.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
631
|
+
if (inline) {
|
|
632
|
+
// The write owns the moved-in value; the slot copies its bits.
|
|
633
|
+
emitter.storeField(ptr, type, v.name, true);
|
|
634
|
+
emitter.releaseHeap(v.name, type);
|
|
635
|
+
}
|
|
636
|
+
else if (isRefCounted(type)) {
|
|
637
|
+
const old = B.tmp();
|
|
638
|
+
B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
639
|
+
emitter.storeField(ptr, type, v.name, false);
|
|
640
|
+
emitter.releaseHeap(old, type);
|
|
641
|
+
}
|
|
642
|
+
else {
|
|
643
|
+
emitter.storeField(ptr, type, v.name, false);
|
|
644
|
+
}
|
|
645
|
+
B.br(join);
|
|
646
|
+
B.startBlock(ln);
|
|
647
|
+
}
|
|
648
|
+
if (!shape.indexValue) {
|
|
649
|
+
// The MISS on a fixed shape: release the moved-in value, throw
|
|
650
|
+
// the catchable TypeError naming the key (scr_record_key_miss —
|
|
651
|
+
// JS would add the property, the documented divergence).
|
|
652
|
+
if (isRefCounted(iv))
|
|
653
|
+
emitter.releaseHeap(v.name, iv);
|
|
654
|
+
emitter.declare(`declare void @scr_record_key_miss(ptr)`);
|
|
655
|
+
B.line(`call void @scr_record_key_miss(ptr ${key.name})`);
|
|
656
|
+
B.br(join);
|
|
657
|
+
B.startBlock(join);
|
|
658
|
+
emitter.emitPendingCheck();
|
|
659
|
+
break;
|
|
660
|
+
}
|
|
661
|
+
const ovf = emitter.recordOvfPtr(obj.name, s.shapeId);
|
|
662
|
+
emitter.mapSet(ovf, "str", vAcc, key.name, v.name);
|
|
663
|
+
B.br(join);
|
|
664
|
+
B.startBlock(join);
|
|
665
|
+
break;
|
|
666
|
+
}
|
|
667
|
+
case "block": {
|
|
668
|
+
if (s.labels === undefined) {
|
|
669
|
+
emitter.emitBlock(s.body);
|
|
670
|
+
break;
|
|
671
|
+
}
|
|
672
|
+
// A labeled block: `break lbl` inside branches to the end label.
|
|
673
|
+
const le = B.newLabel("blk.e");
|
|
674
|
+
emitter.jumpTargets.push({
|
|
675
|
+
kind: "block",
|
|
676
|
+
brkLabel: le,
|
|
677
|
+
contLabel: null,
|
|
678
|
+
labels: s.labels,
|
|
679
|
+
frameDepth: emitter.frames.length,
|
|
680
|
+
scopeDepth: emitter.scopes.length,
|
|
681
|
+
finallyDepth: emitter.finallyStack.length,
|
|
682
|
+
});
|
|
683
|
+
emitter.emitBlock(s.body);
|
|
684
|
+
emitter.jumpTargets.pop();
|
|
685
|
+
B.br(le);
|
|
686
|
+
B.startBlock(le);
|
|
687
|
+
break;
|
|
688
|
+
}
|
|
689
|
+
case "if": {
|
|
690
|
+
const cond = emitter.emitCondition(s.cond);
|
|
691
|
+
const trueLabel = B.newLabel("if.t");
|
|
692
|
+
const joinLabel = B.newLabel("if.j");
|
|
693
|
+
const falseLabel = s.else_ ? B.newLabel("if.f") : joinLabel;
|
|
694
|
+
B.condBr(cond, trueLabel, falseLabel);
|
|
695
|
+
B.startBlock(trueLabel);
|
|
696
|
+
emitter.emitBlock(s.then);
|
|
697
|
+
B.br(joinLabel);
|
|
698
|
+
if (s.else_) {
|
|
699
|
+
B.startBlock(falseLabel);
|
|
700
|
+
emitter.emitBlock(s.else_);
|
|
701
|
+
B.br(joinLabel);
|
|
702
|
+
}
|
|
703
|
+
B.startBlock(joinLabel);
|
|
704
|
+
break;
|
|
705
|
+
}
|
|
706
|
+
case "while": {
|
|
707
|
+
const workerBudget = emitter.workerLoopBudget(s);
|
|
708
|
+
const le = B.newLabel("loop.e");
|
|
709
|
+
emitter.emitLoopCopies(s, true, le, (exit) => {
|
|
710
|
+
const lc = B.newLabel("loop.c");
|
|
711
|
+
const lb = B.newLabel("loop.b");
|
|
712
|
+
const lp = workerBudget !== null ? B.newLabel("loop.p") : lc;
|
|
713
|
+
B.br(lc);
|
|
714
|
+
B.startBlock(lc);
|
|
715
|
+
B.condBr(emitter.emitCondition(s.cond), lb, exit);
|
|
716
|
+
B.startBlock(lb);
|
|
717
|
+
emitter.jumpTargets.push({
|
|
718
|
+
kind: "loop",
|
|
719
|
+
brkLabel: exit,
|
|
720
|
+
contLabel: lp,
|
|
721
|
+
labels: s.labels,
|
|
722
|
+
frameDepth: emitter.frames.length,
|
|
723
|
+
scopeDepth: emitter.scopes.length,
|
|
724
|
+
finallyDepth: emitter.finallyStack.length,
|
|
725
|
+
});
|
|
726
|
+
emitter.emitBlock(s.body);
|
|
727
|
+
emitter.jumpTargets.pop();
|
|
728
|
+
B.br(lp);
|
|
729
|
+
if (lp !== lc) {
|
|
730
|
+
B.startBlock(lp);
|
|
731
|
+
emitter.emitWorkerLoopCheck(workerBudget);
|
|
732
|
+
B.br(lc);
|
|
733
|
+
}
|
|
734
|
+
});
|
|
735
|
+
B.startBlock(le);
|
|
736
|
+
break;
|
|
737
|
+
}
|
|
738
|
+
case "doWhile": {
|
|
739
|
+
const workerBudget = emitter.workerLoopBudget(s);
|
|
740
|
+
// Body first (runs at least once); continue jumps to the CONDITION.
|
|
741
|
+
const le = B.newLabel("loop.e");
|
|
742
|
+
emitter.emitLoopCopies(s, true, le, (exit) => {
|
|
743
|
+
const lb = B.newLabel("loop.b");
|
|
744
|
+
const lc = B.newLabel("loop.c");
|
|
745
|
+
B.br(lb);
|
|
746
|
+
B.startBlock(lb);
|
|
747
|
+
emitter.jumpTargets.push({
|
|
748
|
+
kind: "loop",
|
|
749
|
+
brkLabel: exit,
|
|
750
|
+
contLabel: lc,
|
|
751
|
+
labels: s.labels,
|
|
752
|
+
frameDepth: emitter.frames.length,
|
|
753
|
+
scopeDepth: emitter.scopes.length,
|
|
754
|
+
finallyDepth: emitter.finallyStack.length,
|
|
755
|
+
});
|
|
756
|
+
emitter.emitBlock(s.body);
|
|
757
|
+
emitter.jumpTargets.pop();
|
|
758
|
+
B.br(lc);
|
|
759
|
+
B.startBlock(lc);
|
|
760
|
+
emitter.emitWorkerLoopCheck(workerBudget);
|
|
761
|
+
B.condBr(emitter.emitCondition(s.cond), lb, exit);
|
|
762
|
+
});
|
|
763
|
+
B.startBlock(le);
|
|
764
|
+
break;
|
|
765
|
+
}
|
|
766
|
+
case "for": {
|
|
767
|
+
// The init's scope wraps the whole loop (break/continue must NOT
|
|
768
|
+
// release it — scopeDepth captured after the push, C parity).
|
|
769
|
+
const integerArrayLoop = emitter.debug === null
|
|
770
|
+
? matchIntegerArrayForLoop(s, emitter.currentLocals, emitter.integerArrayBindings)
|
|
771
|
+
: null;
|
|
772
|
+
const integerLoop = integerArrayLoop ??
|
|
773
|
+
(emitter.debug === null ? matchIntegerBytesForLoop(s, emitter.numericLocals) : null);
|
|
774
|
+
const countedLoop = !integerLoop && emitter.countedLoopsEnabled
|
|
775
|
+
? matchIntegerCountedForLoop(s, emitter.numericLocals, emitter.integerRanges, emitter.unaliasedArrays)
|
|
776
|
+
: null;
|
|
777
|
+
const window = countedLoop && emitter.byteWindowsEnabled
|
|
778
|
+
? matchByteWindow(s, countedLoop, emitter.numericLocals, emitter.captureIds, emitter.integerRanges, emitter.byteWindowEntries.get(s) ?? new Set())
|
|
779
|
+
: null;
|
|
780
|
+
const denseShape = !emitter.denseLoopsEnabled
|
|
781
|
+
? null
|
|
782
|
+
: integerArrayLoop
|
|
783
|
+
? {
|
|
784
|
+
counter: integerArrayLoop.localId,
|
|
785
|
+
length: integerArrayLoop.limitReceiver,
|
|
786
|
+
range: { min: 0, max: 4294967294 },
|
|
787
|
+
}
|
|
788
|
+
: countedLoop && !countedLoop.guarded
|
|
789
|
+
? countedDenseShape(s, countedLoop)
|
|
790
|
+
: null;
|
|
791
|
+
const dense = denseShape && !window
|
|
792
|
+
? matchDenseArrayLoop(s, denseShape, emitter.numericLocals, emitter.unaliasedArrays, emitter.denseLoopEntries.get(s) ?? new Set())
|
|
793
|
+
: null;
|
|
794
|
+
if (dense) {
|
|
795
|
+
const valid = emitDenseLoopGuard(emitter, dense);
|
|
796
|
+
const fast = B.newLabel("dense.loop.fast"), slow = B.newLabel("dense.loop.slow"), done = B.newLabel("dense.loop.done");
|
|
797
|
+
B.condBr(valid, fast, slow);
|
|
798
|
+
emitter.denseLoopsEnabled = false;
|
|
799
|
+
try {
|
|
800
|
+
B.startBlock(slow);
|
|
801
|
+
emitter.emitStmt(s);
|
|
802
|
+
B.br(done);
|
|
803
|
+
B.startBlock(fast);
|
|
804
|
+
emitter.denseLoop = dense;
|
|
805
|
+
emitter.emitStmt(s);
|
|
806
|
+
B.br(done);
|
|
807
|
+
}
|
|
808
|
+
finally {
|
|
809
|
+
emitter.denseLoop = null;
|
|
810
|
+
emitter.denseLoopsEnabled = true;
|
|
811
|
+
}
|
|
812
|
+
B.startBlock(done);
|
|
813
|
+
break;
|
|
814
|
+
}
|
|
815
|
+
if (window) {
|
|
816
|
+
const valid = emitByteWindowGuard(emitter, window);
|
|
817
|
+
const fast = B.newLabel("bytes.window.fast"), slow = B.newLabel("bytes.window.slow"), done = B.newLabel("bytes.window.done");
|
|
818
|
+
B.condBr(valid, fast, slow);
|
|
819
|
+
const originalRanges = emitter.integerRanges, originalBounds = emitter.bytesBounds;
|
|
820
|
+
emitter.byteWindowsEnabled = false;
|
|
821
|
+
try {
|
|
822
|
+
B.startBlock(slow);
|
|
823
|
+
emitter.emitStmt(s);
|
|
824
|
+
B.br(done);
|
|
825
|
+
B.startBlock(fast);
|
|
826
|
+
emitter.integerRanges = window.ranges;
|
|
827
|
+
emitter.bytesBounds = new Set([...originalBounds, ...window.bounds]);
|
|
828
|
+
emitter.emitStmt(s);
|
|
829
|
+
B.br(done);
|
|
830
|
+
}
|
|
831
|
+
finally {
|
|
832
|
+
emitter.integerRanges = originalRanges;
|
|
833
|
+
emitter.bytesBounds = originalBounds;
|
|
834
|
+
emitter.byteWindowsEnabled = true;
|
|
835
|
+
}
|
|
836
|
+
B.startBlock(done);
|
|
837
|
+
break;
|
|
838
|
+
}
|
|
839
|
+
const version = emitter.bytesLoopVersionsEnabled &&
|
|
840
|
+
emitter.bytesLoopVersioning.size < MAX_BYTES_LOOP_VERSION_DEPTH &&
|
|
841
|
+
!emitter.bytesLoopVersioning.has(s)
|
|
842
|
+
? emitter.matchBytesLoopVersion(s, countedLoop)
|
|
843
|
+
: null;
|
|
844
|
+
if (version) {
|
|
845
|
+
const fast = B.newLabel("bytes.version.fast"), slow = B.newLabel("bytes.version.slow"), done = B.newLabel("bytes.version.done");
|
|
846
|
+
emitBytesLoopVersionGuard(emitter, version, fast, slow);
|
|
847
|
+
const originalBounds = emitter.bytesBounds, originalRanges = emitter.integerRanges;
|
|
848
|
+
emitter.bytesLoopVersioning.add(s);
|
|
849
|
+
try {
|
|
850
|
+
B.startBlock(slow);
|
|
851
|
+
emitter.emitStmt(s);
|
|
852
|
+
B.br(done);
|
|
853
|
+
B.startBlock(fast);
|
|
854
|
+
emitter.bytesBounds = new Set([...originalBounds, ...version.bounds]);
|
|
855
|
+
if (version.ranges.size > 0)
|
|
856
|
+
emitter.integerRanges = new Map([...originalRanges, ...version.ranges]);
|
|
857
|
+
if (version.counted?.guarded)
|
|
858
|
+
emitter.provenCountedGuards.add(s);
|
|
859
|
+
emitter.emitStmt(s);
|
|
860
|
+
B.br(done);
|
|
861
|
+
}
|
|
862
|
+
finally {
|
|
863
|
+
emitter.bytesBounds = originalBounds;
|
|
864
|
+
emitter.integerRanges = originalRanges;
|
|
865
|
+
emitter.provenCountedGuards.delete(s);
|
|
866
|
+
emitter.bytesLoopVersioning.delete(s);
|
|
867
|
+
}
|
|
868
|
+
B.startBlock(done);
|
|
869
|
+
break;
|
|
870
|
+
}
|
|
871
|
+
let countedJoin = null;
|
|
872
|
+
if (countedLoop?.guarded && !emitter.provenCountedGuards.has(s)) {
|
|
873
|
+
const safe = emitCountedLoopSafety(emitter, countedLoop);
|
|
874
|
+
const fast = B.newLabel("counted.fast");
|
|
875
|
+
const slow = B.newLabel("counted.slow");
|
|
876
|
+
countedJoin = B.newLabel("counted.done");
|
|
877
|
+
B.condBr(safe, fast, slow);
|
|
878
|
+
B.startBlock(slow);
|
|
879
|
+
emitter.countedLoopsEnabled = false;
|
|
880
|
+
emitter.emitStmt(s);
|
|
881
|
+
emitter.countedLoopsEnabled = true;
|
|
882
|
+
B.br(countedJoin);
|
|
883
|
+
B.startBlock(fast);
|
|
884
|
+
}
|
|
885
|
+
emitter.scopes.push([]);
|
|
886
|
+
let integerSlot = null;
|
|
887
|
+
let countedLimit = null;
|
|
888
|
+
if (integerLoop) {
|
|
889
|
+
integerSlot = B.slot();
|
|
890
|
+
B.entryAllocas.push(`${integerSlot} = alloca ${emitter.sizeType} ; integer induction ${emitter.currentLocals.get(integerLoop.localId).name}`);
|
|
891
|
+
let start = "0";
|
|
892
|
+
if (integerArrayLoop && s.init?.kind === "varDecl" && s.init.init) {
|
|
893
|
+
const value = emitter.emitExpr(s.init.init);
|
|
894
|
+
start = B.tmp();
|
|
895
|
+
// The start is 0 or an enclosing array index plus one (at most
|
|
896
|
+
// 2^32 - 1): on 64-bit targets the signed conversion is exact
|
|
897
|
+
// and avoids x86-64's unsigned 64-bit conversion sequence.
|
|
898
|
+
const conversion = emitter.sizeType === "i64" ? "fptosi" : "fptoui";
|
|
899
|
+
B.line(`${start} = ${conversion} double ${value.name} to ${emitter.sizeType}`);
|
|
900
|
+
emitter.integerArrayBindings.add(integerLoop.localId);
|
|
901
|
+
}
|
|
902
|
+
B.line(`store ${emitter.sizeType} ${start}, ptr ${integerSlot}`);
|
|
903
|
+
emitter.integerLoopBindings.set(integerLoop.localId, {
|
|
904
|
+
slot: integerSlot,
|
|
905
|
+
type: emitter.sizeType,
|
|
906
|
+
range: emitter.denseLoop?.counter === integerLoop.localId
|
|
907
|
+
? emitter.denseLoop.range
|
|
908
|
+
: { min: 0, max: integerArrayLoop ? 4294967294 : Number.MAX_SAFE_INTEGER - 1 },
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
else if (countedLoop) {
|
|
912
|
+
integerSlot = B.slot();
|
|
913
|
+
B.entryAllocas.push(`${integerSlot} = alloca i64 ; integer induction ${emitter.currentLocals.get(countedLoop.localId).name}`);
|
|
914
|
+
const startNumber = emitter.emitExpr(countedLoop.start);
|
|
915
|
+
const start = B.tmp();
|
|
916
|
+
B.line(`${start} = fptosi double ${startNumber.name} to i64`);
|
|
917
|
+
B.line(`store i64 ${start}, ptr ${integerSlot}`);
|
|
918
|
+
emitter.integerLoopBindings.set(countedLoop.localId, {
|
|
919
|
+
slot: integerSlot,
|
|
920
|
+
type: "i64",
|
|
921
|
+
signed: true,
|
|
922
|
+
range: emitter.denseLoop?.counter === countedLoop.localId
|
|
923
|
+
? emitter.denseLoop.range
|
|
924
|
+
: countedLoop.range,
|
|
925
|
+
});
|
|
926
|
+
countedLimit = emitCountedLoopLimit(emitter, countedLoop);
|
|
927
|
+
}
|
|
928
|
+
else if (s.init) {
|
|
929
|
+
// A multi-declarator head shares the loop's scope. Emitting its
|
|
930
|
+
// IR block as an ordinary block would release captured/ref locals
|
|
931
|
+
// before the first condition.
|
|
932
|
+
const initializers = s.init.kind === "block" ? s.init.body : [s.init];
|
|
933
|
+
for (const initializer of initializers)
|
|
934
|
+
emitter.emitStmt(initializer);
|
|
935
|
+
}
|
|
936
|
+
const le = B.newLabel("loop.e");
|
|
937
|
+
// JS `for (let i ...)`: each iteration gets a FRESH binding holding
|
|
938
|
+
// a copy of the previous one (closures made in iteration k keep
|
|
939
|
+
// seeing iteration k's value) — only observable, and only emitted,
|
|
940
|
+
// when a let variable is captured (boxed). Freshen before the first
|
|
941
|
+
// condition and again in the continue-target block before updating.
|
|
942
|
+
const initializers = s.init?.kind === "block" ? s.init.body : s.init ? [s.init] : [];
|
|
943
|
+
const capturedLets = initializers.flatMap((init) => {
|
|
944
|
+
const local = init.kind === "varDecl" ? emitter.currentLocals.get(init.localId) : undefined;
|
|
945
|
+
return local?.boxed && local.mutable ? [local] : [];
|
|
946
|
+
});
|
|
947
|
+
const freshenBindings = () => {
|
|
948
|
+
for (const local of capturedLets) {
|
|
949
|
+
const slot = `%${mangleLocal(local.id)}`;
|
|
950
|
+
const fresh = B.tmp();
|
|
951
|
+
const old = B.tmp();
|
|
952
|
+
B.line(`${fresh} = ${boxNewCall(emitter.shapeHost, local.type)} ; per-iteration ${local.name}`);
|
|
953
|
+
B.line(`${old} = load ptr, ptr ${slot}`);
|
|
954
|
+
const val = emitter.boxGet(old, local.type);
|
|
955
|
+
emitter.boxSet(fresh, local.type, val);
|
|
956
|
+
emitter.declare(`declare void @scr_box_release(ptr)`);
|
|
957
|
+
B.line(`call void @scr_box_release(ptr ${old})`);
|
|
958
|
+
B.line(`store ptr ${fresh}, ptr ${slot}`);
|
|
959
|
+
}
|
|
960
|
+
};
|
|
961
|
+
const workerBudget = emitter.workerLoopBudget(s);
|
|
962
|
+
freshenBindings();
|
|
963
|
+
emitter.emitLoopCopies(s, capturedLets.length === 0, le, (exit) => {
|
|
964
|
+
const lc = B.newLabel("loop.c");
|
|
965
|
+
const lb = B.newLabel("loop.b");
|
|
966
|
+
const lu = s.update || capturedLets.length > 0 || workerBudget !== null ? B.newLabel("loop.u") : lc;
|
|
967
|
+
B.br(lc);
|
|
968
|
+
B.startBlock(lc);
|
|
969
|
+
if (integerLoop && integerSlot) {
|
|
970
|
+
const receiver = emitter.emitStableReceiver(integerLoop.limitReceiver, []);
|
|
971
|
+
const lenPtr = B.tmp();
|
|
972
|
+
const len = B.tmp();
|
|
973
|
+
const index = B.tmp();
|
|
974
|
+
const inBounds = B.tmp();
|
|
975
|
+
B.line(`${lenPtr} = getelementptr inbounds %${integerArrayLoop ? "ScrArr" : "ScrBytes"}, ptr ${receiver.name}, i64 0, i32 1`);
|
|
976
|
+
emitter.markMemoryPointer(lenPtr, integerArrayLoop ? "array:header" : "bytes:header");
|
|
977
|
+
B.line(`${len} = load ${emitter.sizeType}, ptr ${lenPtr}${emitter.fieldAliasAttachment(lenPtr)}`);
|
|
978
|
+
B.line(`${index} = load ${emitter.sizeType}, ptr ${integerSlot}`);
|
|
979
|
+
B.line(`${inBounds} = icmp ult ${emitter.sizeType} ${index}, ${len}`);
|
|
980
|
+
B.condBr(inBounds, lb, exit);
|
|
981
|
+
}
|
|
982
|
+
else if (countedLoop && integerSlot && countedLimit) {
|
|
983
|
+
const index = B.tmp();
|
|
984
|
+
const inBounds = B.tmp();
|
|
985
|
+
B.line(`${index} = load i64, ptr ${integerSlot}`);
|
|
986
|
+
B.line(`${inBounds} = icmp ${countedLoop.step > 0 ? "slt" : "sgt"} i64 ${index}, ${countedLimit}`);
|
|
987
|
+
B.condBr(inBounds, lb, exit);
|
|
988
|
+
}
|
|
989
|
+
else if (s.cond)
|
|
990
|
+
B.condBr(emitter.emitCondition(s.cond), lb, exit);
|
|
991
|
+
else
|
|
992
|
+
B.br(lb);
|
|
993
|
+
B.startBlock(lb);
|
|
994
|
+
emitter.jumpTargets.push({
|
|
995
|
+
kind: "loop",
|
|
996
|
+
brkLabel: exit,
|
|
997
|
+
contLabel: lu,
|
|
998
|
+
labels: s.labels,
|
|
999
|
+
frameDepth: emitter.frames.length,
|
|
1000
|
+
scopeDepth: emitter.scopes.length,
|
|
1001
|
+
finallyDepth: emitter.finallyStack.length,
|
|
1002
|
+
});
|
|
1003
|
+
emitter.emitBlock(s.body);
|
|
1004
|
+
emitter.jumpTargets.pop();
|
|
1005
|
+
B.br(lu);
|
|
1006
|
+
if (lu !== lc) {
|
|
1007
|
+
B.startBlock(lu);
|
|
1008
|
+
emitter.emitWorkerLoopCheck(workerBudget);
|
|
1009
|
+
freshenBindings();
|
|
1010
|
+
if (integerLoop && integerSlot) {
|
|
1011
|
+
const old = B.tmp();
|
|
1012
|
+
const next = B.tmp();
|
|
1013
|
+
B.line(`${old} = load ${emitter.sizeType}, ptr ${integerSlot}`);
|
|
1014
|
+
B.line(`${next} = add nuw ${emitter.sizeType} ${old}, 1`);
|
|
1015
|
+
B.line(`store ${emitter.sizeType} ${next}, ptr ${integerSlot}`);
|
|
1016
|
+
}
|
|
1017
|
+
else if (countedLoop && integerSlot) {
|
|
1018
|
+
const old = B.tmp();
|
|
1019
|
+
const next = B.tmp();
|
|
1020
|
+
B.line(`${old} = load i64, ptr ${integerSlot}`);
|
|
1021
|
+
B.line(`${next} = add nsw i64 ${old}, ${countedLoop.step}`);
|
|
1022
|
+
B.line(`store i64 ${next}, ptr ${integerSlot}`);
|
|
1023
|
+
}
|
|
1024
|
+
else if (s.update)
|
|
1025
|
+
emitter.emitStmt(s.update);
|
|
1026
|
+
B.br(lc);
|
|
1027
|
+
}
|
|
1028
|
+
});
|
|
1029
|
+
B.startBlock(le);
|
|
1030
|
+
emitter.releaseScope(emitter.scopes.pop());
|
|
1031
|
+
if (integerLoop)
|
|
1032
|
+
emitter.integerLoopBindings.delete(integerLoop.localId);
|
|
1033
|
+
if (countedLoop)
|
|
1034
|
+
emitter.integerLoopBindings.delete(countedLoop.localId);
|
|
1035
|
+
if (integerArrayLoop)
|
|
1036
|
+
emitter.integerArrayBindings.delete(integerArrayLoop.localId);
|
|
1037
|
+
if (countedJoin) {
|
|
1038
|
+
B.br(countedJoin);
|
|
1039
|
+
B.startBlock(countedJoin);
|
|
1040
|
+
}
|
|
1041
|
+
break;
|
|
1042
|
+
}
|
|
1043
|
+
case "forOf": {
|
|
1044
|
+
// Ascending index loop; the length is re-read every iteration
|
|
1045
|
+
// (JS-exact — pushes inside the body extend the iteration). The
|
|
1046
|
+
// iterable temp lives in this statement's frame, so it is released
|
|
1047
|
+
// when the whole loop ends (and by `return`'s frame sweep).
|
|
1048
|
+
if (s.iterable.type.kind !== "array")
|
|
1049
|
+
throw new LlvmUnsupportedError(`forOf:${s.iterable.type.kind}`, s.loc);
|
|
1050
|
+
const elem = s.iterable.type.elem;
|
|
1051
|
+
const stored = s.iterable.kind === "varRef" ? emitter.storedSplits.get(s.iterable.localId) : undefined;
|
|
1052
|
+
const direct = emitter.streamingSplitsEnabled ? stringSplit(s.iterable) : null;
|
|
1053
|
+
const snapshot = stored
|
|
1054
|
+
? loadSplitSnapshot(emitter, stored)
|
|
1055
|
+
: direct
|
|
1056
|
+
? emitSplitSnapshot(emitter, direct)
|
|
1057
|
+
: null;
|
|
1058
|
+
const arr = snapshot ? null : emitter.emitExpr(s.iterable);
|
|
1059
|
+
const cursor = snapshot ? emitSplitCursor(emitter, snapshot) : null;
|
|
1060
|
+
const scratch = snapshot ? emitSplitScratch(emitter) : null;
|
|
1061
|
+
const deferred = snapshot && canDeferSplitPiece(s, emitter.currentLocals.get(s.localId));
|
|
1062
|
+
const spanLength = deferred ? B.slot() : null;
|
|
1063
|
+
if (spanLength)
|
|
1064
|
+
B.entryAllocas.push(`${spanLength} = alloca ${emitter.sizeType}`);
|
|
1065
|
+
const idxSlot = snapshot ? null : B.slot();
|
|
1066
|
+
if (idxSlot) {
|
|
1067
|
+
B.entryAllocas.push(`${idxSlot} = alloca double`);
|
|
1068
|
+
B.line(`store double ${f64Lit(0)}, ptr ${idxSlot}`);
|
|
1069
|
+
}
|
|
1070
|
+
const lc = B.newLabel("fof.c");
|
|
1071
|
+
const lb = B.newLabel("fof.b");
|
|
1072
|
+
const lu = B.newLabel("fof.u");
|
|
1073
|
+
const le = B.newLabel("fof.e");
|
|
1074
|
+
const workerBudget = emitter.workerLoopBudget(s);
|
|
1075
|
+
B.br(lc);
|
|
1076
|
+
B.startBlock(lc);
|
|
1077
|
+
const inBounds = B.tmp();
|
|
1078
|
+
let cur;
|
|
1079
|
+
if (snapshot && cursor && scratch) {
|
|
1080
|
+
cur = spanLength
|
|
1081
|
+
? emitSplitSpanNext(emitter, snapshot, cursor, spanLength)
|
|
1082
|
+
: emitSplitNext(emitter, snapshot, cursor, scratch);
|
|
1083
|
+
B.line(`${inBounds} = icmp ne ptr ${cur}, null`);
|
|
1084
|
+
}
|
|
1085
|
+
else {
|
|
1086
|
+
const i = B.tmp(), lenPtr = B.tmp(), rawLen = B.tmp(), len = B.tmp();
|
|
1087
|
+
B.line(`${i} = load double, ptr ${idxSlot}`);
|
|
1088
|
+
// The inline form of scr_arr_len, like the `length` intrinsic.
|
|
1089
|
+
B.line(`${lenPtr} = getelementptr inbounds %ScrArr, ptr ${arr.name}, i32 0, i32 1`);
|
|
1090
|
+
emitter.markMemoryPointer(lenPtr, "array:header");
|
|
1091
|
+
B.line(`${rawLen} = load ${emitter.sizeType}, ptr ${lenPtr}${emitter.fieldAliasAttachment(lenPtr)}${emitter.arrayLengthRange}`);
|
|
1092
|
+
B.line(`${len} = ${sizeToDouble(emitter.sizeType)} ${emitter.sizeType} ${rawLen} to double`);
|
|
1093
|
+
B.line(`${inBounds} = fcmp olt double ${i}, ${len}`);
|
|
1094
|
+
cur = i;
|
|
1095
|
+
}
|
|
1096
|
+
B.condBr(inBounds, lb, le);
|
|
1097
|
+
B.startBlock(lb);
|
|
1098
|
+
emitter.jumpTargets.push({
|
|
1099
|
+
kind: "loop",
|
|
1100
|
+
brkLabel: le,
|
|
1101
|
+
contLabel: lu,
|
|
1102
|
+
labels: s.labels,
|
|
1103
|
+
frameDepth: emitter.frames.length,
|
|
1104
|
+
scopeDepth: emitter.scopes.length,
|
|
1105
|
+
finallyDepth: emitter.finallyStack.length,
|
|
1106
|
+
});
|
|
1107
|
+
// The loop variable is a fresh const per iteration: its scope opens
|
|
1108
|
+
// here, holds the (for ref elements: owned +1) current element, and
|
|
1109
|
+
// releases it at the end of each iteration.
|
|
1110
|
+
emitter.scopes.push([]);
|
|
1111
|
+
const localInfo = emitter.currentLocals.get(s.localId);
|
|
1112
|
+
const slot = `%${mangleLocal(s.localId)}`;
|
|
1113
|
+
const borrowedElement = !snapshot && emitter.loopArrayBorrows.has(s);
|
|
1114
|
+
if (!snapshot) {
|
|
1115
|
+
const acc = elemAccess(elem);
|
|
1116
|
+
const getter = borrowedElement ? "scr_arr_borrow_ref" : `scr_arr_get_${acc}`;
|
|
1117
|
+
cur = emitDenseArrayGet(emitter, arr.name, { name: cur, type: { kind: "f64" } }, undefined, acc, elem, getter, !borrowedElement);
|
|
1118
|
+
}
|
|
1119
|
+
if (spanLength) {
|
|
1120
|
+
const length = B.tmp();
|
|
1121
|
+
B.line(`${length} = load ${emitter.sizeType}, ptr ${spanLength}`);
|
|
1122
|
+
emitter.splitSpans.set(s.localId, { bytes: cur, length, scratch: scratch });
|
|
1123
|
+
cur = "null";
|
|
1124
|
+
}
|
|
1125
|
+
if (localInfo?.boxed) {
|
|
1126
|
+
// Captured loop variable: a fresh box per iteration, matching the
|
|
1127
|
+
// fresh const binding. The box takes ownership of a ref element's
|
|
1128
|
+
// +1 and is released with the iteration's scope.
|
|
1129
|
+
const box = B.tmp();
|
|
1130
|
+
B.line(`${box} = ${boxNewCall(emitter.shapeHost, elem)} ; per-iteration ${localInfo.name}`);
|
|
1131
|
+
emitter.boxSet(box, elem, cur);
|
|
1132
|
+
B.line(`store ptr ${box}, ptr ${slot}`);
|
|
1133
|
+
emitter.scopes[emitter.scopes.length - 1].push({ slot, type: elem, boxed: true });
|
|
1134
|
+
}
|
|
1135
|
+
else {
|
|
1136
|
+
B.line(`store ${emitter.llType(elem)} ${cur}, ptr ${slot}`);
|
|
1137
|
+
if (isRefCounted(elem) && !borrowedElement)
|
|
1138
|
+
emitter.scopes[emitter.scopes.length - 1].push({ slot, type: elem });
|
|
1139
|
+
}
|
|
1140
|
+
emitter.emitStmts(s.body);
|
|
1141
|
+
if (spanLength)
|
|
1142
|
+
emitter.splitSpans.delete(s.localId);
|
|
1143
|
+
const endedWithJump = endsWithJump(s.body);
|
|
1144
|
+
const scope = emitter.scopes.pop();
|
|
1145
|
+
if (!endedWithJump)
|
|
1146
|
+
emitter.releaseScope(scope);
|
|
1147
|
+
emitter.jumpTargets.pop();
|
|
1148
|
+
B.br(lu);
|
|
1149
|
+
B.startBlock(lu);
|
|
1150
|
+
emitter.emitWorkerLoopCheck(workerBudget);
|
|
1151
|
+
if (idxSlot) {
|
|
1152
|
+
const i2 = B.tmp(), i3 = B.tmp();
|
|
1153
|
+
B.line(`${i2} = load double, ptr ${idxSlot}`);
|
|
1154
|
+
B.line(`${i3} = fadd double ${i2}, ${f64Lit(1)}`);
|
|
1155
|
+
B.line(`store double ${i3}, ptr ${idxSlot}`);
|
|
1156
|
+
}
|
|
1157
|
+
B.br(lc);
|
|
1158
|
+
B.startBlock(le);
|
|
1159
|
+
break;
|
|
1160
|
+
}
|
|
1161
|
+
case "switch":
|
|
1162
|
+
emitter.emitSwitch(s);
|
|
1163
|
+
break;
|
|
1164
|
+
case "break": {
|
|
1165
|
+
// Unlabeled: the innermost loop OR switch (labeled blocks are
|
|
1166
|
+
// skipped); labeled: the entry carrying the label.
|
|
1167
|
+
let target;
|
|
1168
|
+
for (let i = emitter.jumpTargets.length - 1; i >= 0; i--) {
|
|
1169
|
+
const t = emitter.jumpTargets[i];
|
|
1170
|
+
if (s.label !== undefined ? t.labels?.includes(s.label) : t.kind !== "block") {
|
|
1171
|
+
target = t;
|
|
1172
|
+
break;
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
if (!target)
|
|
1176
|
+
throw new InternalCompilerError("llvm emitter bug: break target not found");
|
|
1177
|
+
emitter.emitFinallysForJump(target.finallyDepth, target.frameDepth, target.scopeDepth);
|
|
1178
|
+
if (!B.isTerminated())
|
|
1179
|
+
B.terminate(`br label %${target.brkLabel}`);
|
|
1180
|
+
break;
|
|
1181
|
+
}
|
|
1182
|
+
case "continue": {
|
|
1183
|
+
// Unlabeled: the innermost loop; labeled: the loop carrying the
|
|
1184
|
+
// label (tsc + the validator guarantee it IS a loop).
|
|
1185
|
+
let target;
|
|
1186
|
+
for (let i = emitter.jumpTargets.length - 1; i >= 0; i--) {
|
|
1187
|
+
const t = emitter.jumpTargets[i];
|
|
1188
|
+
if (t.kind === "loop" && (s.label === undefined || t.labels?.includes(s.label))) {
|
|
1189
|
+
target = t;
|
|
1190
|
+
break;
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
if (!target || target.contLabel === null)
|
|
1194
|
+
throw new InternalCompilerError("llvm emitter bug: continue target not found");
|
|
1195
|
+
emitter.emitFinallysForJump(target.finallyDepth, target.frameDepth, target.scopeDepth);
|
|
1196
|
+
if (!B.isTerminated())
|
|
1197
|
+
B.terminate(`br label %${target.contLabel}`);
|
|
1198
|
+
break;
|
|
1199
|
+
}
|
|
1200
|
+
case "return": {
|
|
1201
|
+
// The value computes FIRST (an SSA temp — finally mutations of
|
|
1202
|
+
// returned locals cannot change it, Node-exact), then every
|
|
1203
|
+
// crossed finally runs innermost-first with the frames/scopes/
|
|
1204
|
+
// tryStack it sees truncated to its region (its releases already
|
|
1205
|
+
// ran; a throw inside a copy propagates OUT of the completing
|
|
1206
|
+
// try, past its own catch), then the function-level releases and
|
|
1207
|
+
// the actual ret. The parked value owns a synthetic slot-backed
|
|
1208
|
+
// scope entry during each copy so a throwing finally releases it.
|
|
1209
|
+
const adopted = emitter.finallyStack.length > 0 || emitter.tryStack.length > 0
|
|
1210
|
+
? adoptingAwaitOf(s.value)
|
|
1211
|
+
: null;
|
|
1212
|
+
if (adopted !== null) {
|
|
1213
|
+
emitter.emitAdoptingReturn(s, adopted);
|
|
1214
|
+
break;
|
|
1215
|
+
}
|
|
1216
|
+
let v = null;
|
|
1217
|
+
const moved = emitter.finallyStack.length === 0 && !emitter.currentUnionResult
|
|
1218
|
+
? emitter.movableReturn(s.value)
|
|
1219
|
+
: null;
|
|
1220
|
+
if (s.value !== null && emitter.currentUnionResult) {
|
|
1221
|
+
// The tag and payload bits leave in registers; a heap box the
|
|
1222
|
+
// value needed is released with its frame below.
|
|
1223
|
+
const box = emitter.emitUnionProjection(s.value);
|
|
1224
|
+
v = { name: emitter.scalarUnionPair(box.name, s.value.type), type: s.value.type };
|
|
1225
|
+
}
|
|
1226
|
+
else if (moved !== null) {
|
|
1227
|
+
// Returning an owned local hands its reference to the caller: no
|
|
1228
|
+
// retain now and no release of the local below.
|
|
1229
|
+
const t = B.tmp();
|
|
1230
|
+
B.line(`${t} = load ptr, ptr ${moved.entry.slot}`);
|
|
1231
|
+
v = { name: t, type: s.value.type };
|
|
1232
|
+
moved.scope.splice(moved.scope.indexOf(moved.entry), 1);
|
|
1233
|
+
emitter.releaseForJump(0, 0);
|
|
1234
|
+
moved.scope.splice(moved.index, 0, moved.entry);
|
|
1235
|
+
}
|
|
1236
|
+
else if (s.value !== null && emitter.currentBorrowedReturn) {
|
|
1237
|
+
// A borrowed-return body hands back its walk without a reference
|
|
1238
|
+
// (it has no try statements, so no finally can intervene). An
|
|
1239
|
+
// optional element read lends the element its array keeps alive.
|
|
1240
|
+
const read = emitter.optionalArrayReads.get(s.value);
|
|
1241
|
+
if (read) {
|
|
1242
|
+
const slot = B.slot();
|
|
1243
|
+
B.entryAllocas.push(`${slot} = alloca ptr`);
|
|
1244
|
+
emitLocalArrayRead(emitter, { ...read, borrow: true }, slot);
|
|
1245
|
+
const t = B.tmp();
|
|
1246
|
+
B.line(`${t} = load ptr, ptr ${slot}`);
|
|
1247
|
+
v = { name: t, type: s.value.type };
|
|
1248
|
+
}
|
|
1249
|
+
else
|
|
1250
|
+
v = emitter.emitReadReceiver(s.value);
|
|
1251
|
+
}
|
|
1252
|
+
else if (s.value !== null) {
|
|
1253
|
+
v = emitter.emitExpr(s.value);
|
|
1254
|
+
if (emitter.currentCoro !== null)
|
|
1255
|
+
emitter.toHeap(v);
|
|
1256
|
+
else
|
|
1257
|
+
emitter.toFrame(v);
|
|
1258
|
+
}
|
|
1259
|
+
// An async generator's `return v` awaits v before any crossed
|
|
1260
|
+
// finally runs. Past finally regions that turn is taken here and
|
|
1261
|
+
// the request settles at completion; otherwise the completion's
|
|
1262
|
+
// own turn is the await (nothing runs in between).
|
|
1263
|
+
const genSettles = emitter.currentAsyncGenerator && (s.awaited === true || emitter.finallyStack.length > 0);
|
|
1264
|
+
// A completion turn that awaits x replaces a return() request's
|
|
1265
|
+
// already-taken await.
|
|
1266
|
+
if (emitter.currentAsyncGenerator && !genSettles) {
|
|
1267
|
+
emitter.declare(`declare void @scr_async_gen_return_awaits()`);
|
|
1268
|
+
B.line(`call void @scr_async_gen_return_awaits()`);
|
|
1269
|
+
}
|
|
1270
|
+
if (emitter.currentAsyncGenerator && s.awaited !== true && emitter.finallyStack.length > 0) {
|
|
1271
|
+
if (emitter.wasi)
|
|
1272
|
+
emitter.emitWasiSuspend(null);
|
|
1273
|
+
else {
|
|
1274
|
+
emitter.declare(`declare void @scr_await_hop()`);
|
|
1275
|
+
B.line(`call void @scr_await_hop()`);
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
if (emitter.finallyStack.length > 0) {
|
|
1279
|
+
let pretSlot = null;
|
|
1280
|
+
if (v !== null && isRefCounted(v.type) && !emitter.currentUnionResult) {
|
|
1281
|
+
pretSlot = B.slot();
|
|
1282
|
+
B.entryAllocas.push(`${pretSlot} = alloca ptr ; pending return (through finally)`);
|
|
1283
|
+
B.line(`store ptr ${v.name}, ptr ${pretSlot}`);
|
|
1284
|
+
}
|
|
1285
|
+
const savedFrames = emitter.frames;
|
|
1286
|
+
const savedScopes = emitter.scopes;
|
|
1287
|
+
const savedFinally = emitter.finallyStack;
|
|
1288
|
+
const savedTry = emitter.tryStack;
|
|
1289
|
+
for (let i = savedFinally.length - 1; i >= 0 && !B.isTerminated(); i--) {
|
|
1290
|
+
const fin = savedFinally[i];
|
|
1291
|
+
emitter.releaseForJump(fin.frameDepth, fin.scopeDepth);
|
|
1292
|
+
emitter.frames = emitter.frames.slice(0, fin.frameDepth);
|
|
1293
|
+
emitter.scopes = emitter.scopes.slice(0, fin.scopeDepth);
|
|
1294
|
+
emitter.finallyStack = savedFinally.slice(0, i);
|
|
1295
|
+
emitter.tryStack = savedTry.slice(0, fin.tryDepth);
|
|
1296
|
+
if (pretSlot !== null)
|
|
1297
|
+
emitter.scopes.push([{ slot: pretSlot, type: v.type }]);
|
|
1298
|
+
emitter.emitBlock(fin.body);
|
|
1299
|
+
if (pretSlot !== null)
|
|
1300
|
+
emitter.scopes.pop();
|
|
1301
|
+
}
|
|
1302
|
+
if (!B.isTerminated())
|
|
1303
|
+
emitter.releaseForJump(0, 0);
|
|
1304
|
+
emitter.frames = savedFrames;
|
|
1305
|
+
emitter.scopes = savedScopes;
|
|
1306
|
+
emitter.finallyStack = savedFinally;
|
|
1307
|
+
emitter.tryStack = savedTry;
|
|
1308
|
+
}
|
|
1309
|
+
else if (moved === null) {
|
|
1310
|
+
emitter.releaseForJump(0, 0);
|
|
1311
|
+
}
|
|
1312
|
+
if (!B.isTerminated()) {
|
|
1313
|
+
if (genSettles)
|
|
1314
|
+
emitter.emitAsyncGenSettled();
|
|
1315
|
+
if (emitter.currentCoro !== null) {
|
|
1316
|
+
emitter.emitWasiFulfill(v);
|
|
1317
|
+
B.terminate(`br label %${emitter.currentCoro.finalLabel}`);
|
|
1318
|
+
}
|
|
1319
|
+
else if (v === null)
|
|
1320
|
+
B.terminate("ret void");
|
|
1321
|
+
else if (emitter.currentInt32Result)
|
|
1322
|
+
B.terminate(`ret i32 ${emitter.int32Argument(v, s.value)}`);
|
|
1323
|
+
else if (emitter.currentUnionResult)
|
|
1324
|
+
B.terminate(`ret ${SCALAR_UNION_RESULT} ${v.name}`);
|
|
1325
|
+
else
|
|
1326
|
+
B.terminate(`ret ${emitter.llType(s.value.type)} ${v.name}`);
|
|
1327
|
+
}
|
|
1328
|
+
break;
|
|
1329
|
+
}
|
|
1330
|
+
case "throw": {
|
|
1331
|
+
// Evaluate, move ownership into the runtime's exception cell, then
|
|
1332
|
+
// unwind unconditionally (the innermost try handler, or out of the
|
|
1333
|
+
// function) — the same release path as return/break/continue.
|
|
1334
|
+
const v = emitter.emitExpr(s.value);
|
|
1335
|
+
if (isRefCounted(s.value.type))
|
|
1336
|
+
emitter.toHeap(v); // the cell takes ownership
|
|
1337
|
+
emitter.emitThrowValue({ name: v.name, type: s.value.type });
|
|
1338
|
+
emitter.emitUnwind();
|
|
1339
|
+
break;
|
|
1340
|
+
}
|
|
1341
|
+
case "rethrow": {
|
|
1342
|
+
// Re-raise the saved snapshot (payload retained — the binding
|
|
1343
|
+
// local releases with its scope) and unwind like `throw`.
|
|
1344
|
+
const c = emitter.emitExpr({ kind: "varRef", localId: s.localId, type: CAUGHT, loc: s.loc });
|
|
1345
|
+
emitter.declare(`declare void @scr_rethrow(ptr)`);
|
|
1346
|
+
B.line(`call void @scr_rethrow(ptr ${c.name})`);
|
|
1347
|
+
emitter.emitUnwind();
|
|
1348
|
+
break;
|
|
1349
|
+
}
|
|
1350
|
+
case "runtimeFence": {
|
|
1351
|
+
// The deferred JS compile fence: throw a catchable Error naming
|
|
1352
|
+
// the construct (message) with the SC code stamped on `code`,
|
|
1353
|
+
// then unwind exactly like `throw`. SCR_ERR_ERROR = 0.
|
|
1354
|
+
const bytes = Buffer.byteLength(s.message, "utf8");
|
|
1355
|
+
emitter.declare(`declare void @scr_throw_error_msg_code(i32, ptr, ${emitter.sizeType}, ptr)`);
|
|
1356
|
+
B.line(`call void @scr_throw_error_msg_code(i32 0, ptr ${emitter.cstr(s.message)}, ${emitter.sizeType} ${bytes}, ptr ${emitter.cstr(s.code)})`);
|
|
1357
|
+
emitter.emitUnwind();
|
|
1358
|
+
break;
|
|
1359
|
+
}
|
|
1360
|
+
case "tryCatch":
|
|
1361
|
+
emitter.emitTryCatch(s);
|
|
1362
|
+
break;
|
|
1363
|
+
default: {
|
|
1364
|
+
// Statement coverage is now total (bytesSet closed the set) —
|
|
1365
|
+
// keep throwing LlvmUnsupportedError for any future IR statement kind.
|
|
1366
|
+
const rest = s;
|
|
1367
|
+
const k = rest.kind;
|
|
1368
|
+
throw new LlvmUnsupportedError(`stmt:${k}`, rest.loc);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
const frame = emitter.frames.pop();
|
|
1372
|
+
// return/throw already released their frames on the jump path; the
|
|
1373
|
+
// fall-through releases after them would be dead double-release code.
|
|
1374
|
+
if (s.kind !== "return" &&
|
|
1375
|
+
s.kind !== "throw" &&
|
|
1376
|
+
s.kind !== "rethrow" &&
|
|
1377
|
+
s.kind !== "runtimeFence") {
|
|
1378
|
+
emitter.releaseTemps(frame);
|
|
1379
|
+
}
|
|
1380
|
+
}
|
|
1381
|
+
/** try/catch/finally via pending-flag unwinding — stmts.ts's
|
|
1382
|
+
* emitTryCatch, block-flavored. Entering a try emits NO code: the try
|
|
1383
|
+
* context is compile-time state (tryStack) redirecting unwinds inside
|
|
1384
|
+
* the region to a label here. Shape:
|
|
1385
|
+
*
|
|
1386
|
+
* { try body } unwinds inside release frames/scopes down to
|
|
1387
|
+
* this statement's depths, then br the handler
|
|
1388
|
+
* br after (normal completion skips the handler)
|
|
1389
|
+
* try.c: (emitted only when some unwind targets it)
|
|
1390
|
+
* binding = scr_exc_take() (or scr_exc_clear() when bindingless)
|
|
1391
|
+
* { catch body }
|
|
1392
|
+
* after: { finally body } normal path
|
|
1393
|
+
* br try.e
|
|
1394
|
+
* try.fx: exception path: the pending exception is
|
|
1395
|
+
* stash = scr_exc_take() STASHED across the finally body so the
|
|
1396
|
+
* { finally body } body's own pending checks answer for
|
|
1397
|
+
* scr_rethrow(stash) themselves; a throw inside REPLACES the
|
|
1398
|
+
* <unwind> stash (it unwinds through the synthetic
|
|
1399
|
+
* try.e: scope entry) — JS's semantics exactly
|
|
1400
|
+
*
|
|
1401
|
+
* Abrupt completions inside tryBody/catchBody ride the finallyStack:
|
|
1402
|
+
* returns inline copies at the return site, while break/continue use the
|
|
1403
|
+
* shared region walk before branching to their resolved target. */
|
|
1404
|
+
export function emitTryCatch(emitter, s) {
|
|
1405
|
+
const B = emitter.B;
|
|
1406
|
+
const hasCatch = s.catchBody !== null;
|
|
1407
|
+
const hasFinally = s.finallyBody !== null;
|
|
1408
|
+
const catchLabel = B.newLabel("try.c");
|
|
1409
|
+
const finExcLabel = B.newLabel("try.fx");
|
|
1410
|
+
const endLabel = B.newLabel("try.e");
|
|
1411
|
+
const afterTryLabel = hasFinally ? B.newLabel("try.f") : endLabel;
|
|
1412
|
+
const handler = {
|
|
1413
|
+
label: hasCatch ? catchLabel : finExcLabel,
|
|
1414
|
+
used: false,
|
|
1415
|
+
frameDepth: emitter.frames.length,
|
|
1416
|
+
scopeDepth: emitter.scopes.length,
|
|
1417
|
+
};
|
|
1418
|
+
if (hasFinally) {
|
|
1419
|
+
emitter.finallyStack.push({
|
|
1420
|
+
frameDepth: emitter.frames.length,
|
|
1421
|
+
scopeDepth: emitter.scopes.length,
|
|
1422
|
+
tryDepth: emitter.tryStack.length,
|
|
1423
|
+
body: s.finallyBody,
|
|
1424
|
+
});
|
|
1425
|
+
}
|
|
1426
|
+
emitter.tryStack.push(handler);
|
|
1427
|
+
emitter.emitBlock(s.tryBody);
|
|
1428
|
+
emitter.tryStack.pop();
|
|
1429
|
+
B.br(afterTryLabel); // no-op when the try body already terminated
|
|
1430
|
+
// Exceptions raised in the CATCH body unwind to the exception-path
|
|
1431
|
+
// finally (pending stays set through it) when one exists.
|
|
1432
|
+
const excHandler = {
|
|
1433
|
+
label: finExcLabel,
|
|
1434
|
+
used: !hasCatch && handler.used,
|
|
1435
|
+
frameDepth: emitter.frames.length,
|
|
1436
|
+
scopeDepth: emitter.scopes.length,
|
|
1437
|
+
};
|
|
1438
|
+
if (hasCatch && handler.used) {
|
|
1439
|
+
B.startBlock(catchLabel);
|
|
1440
|
+
if (hasFinally)
|
|
1441
|
+
emitter.tryStack.push(excHandler);
|
|
1442
|
+
if (emitter.currentGenerator !== null) {
|
|
1443
|
+
// Generator bodies: a pending GENRET sentinel (.return(v)
|
|
1444
|
+
// injected at a yield) is a RETURN completion, not a throw —
|
|
1445
|
+
// catch must not take it. Re-unwind past this handler (finally
|
|
1446
|
+
// still runs — the unwind targets the exception-path finally or
|
|
1447
|
+
// the enclosing context; the depths here equal the handler's).
|
|
1448
|
+
emitter.declare(`declare zeroext i1 @scr_exc_genret_pending()`);
|
|
1449
|
+
const gr = B.tmp();
|
|
1450
|
+
B.line(`${gr} = call zeroext i1 @scr_exc_genret_pending()`);
|
|
1451
|
+
const lg = B.newLabel("try.gr");
|
|
1452
|
+
const lk = B.newLabel("try.gk");
|
|
1453
|
+
B.condBr(gr, lg, lk);
|
|
1454
|
+
B.startBlock(lg);
|
|
1455
|
+
emitter.emitUnwind();
|
|
1456
|
+
B.startBlock(lk);
|
|
1457
|
+
}
|
|
1458
|
+
if (s.catchLocalId !== null) {
|
|
1459
|
+
// catch (e): the exception MOVES into the binding's snapshot box,
|
|
1460
|
+
// owned by the catch body's scope (released on every exit —
|
|
1461
|
+
// normal fall-through, jumps out, and unwinds from the body).
|
|
1462
|
+
const slot = `%${mangleLocal(s.catchLocalId)}`;
|
|
1463
|
+
emitter.declare(`declare ptr @scr_exc_take()`);
|
|
1464
|
+
emitter.emitBlock(s.catchBody, (scope) => {
|
|
1465
|
+
const c = B.tmp();
|
|
1466
|
+
B.line(`${c} = call ptr @scr_exc_take() ; catch binding`);
|
|
1467
|
+
if (emitter.currentLocals.get(s.catchLocalId)?.boxed) {
|
|
1468
|
+
const box = B.tmp();
|
|
1469
|
+
B.line(`${box} = ${boxNewCall(emitter.shapeHost, CAUGHT)} ; captured exception`);
|
|
1470
|
+
emitter.boxSet(box, CAUGHT, c);
|
|
1471
|
+
B.line(`store ptr ${box}, ptr ${slot}`);
|
|
1472
|
+
scope.push({ slot, type: CAUGHT, boxed: true });
|
|
1473
|
+
}
|
|
1474
|
+
else {
|
|
1475
|
+
B.line(`store ptr ${c}, ptr ${slot}`);
|
|
1476
|
+
scope.push({ slot, type: CAUGHT });
|
|
1477
|
+
}
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
else {
|
|
1481
|
+
emitter.declare(`declare void @scr_exc_clear()`);
|
|
1482
|
+
B.line(`call void @scr_exc_clear() ; catch takes the exception`);
|
|
1483
|
+
emitter.emitBlock(s.catchBody);
|
|
1484
|
+
}
|
|
1485
|
+
if (hasFinally)
|
|
1486
|
+
emitter.tryStack.pop();
|
|
1487
|
+
B.br(afterTryLabel); // the catch's normal completion
|
|
1488
|
+
}
|
|
1489
|
+
if (hasFinally)
|
|
1490
|
+
emitter.finallyStack.pop();
|
|
1491
|
+
if (hasFinally) {
|
|
1492
|
+
B.startBlock(afterTryLabel);
|
|
1493
|
+
emitter.emitBlock(s.finallyBody); // normal path
|
|
1494
|
+
B.br(endLabel);
|
|
1495
|
+
if (excHandler.used) {
|
|
1496
|
+
// The pending exception is STASHED across the finally body (a
|
|
1497
|
+
// ScrCaught snapshot, re-raised after) so the body runs with a
|
|
1498
|
+
// CLEAN cell — see stmts.ts's exception-path copy. The
|
|
1499
|
+
// stash rides an alloca slot so a throw inside the body unwinds
|
|
1500
|
+
// through the synthetic scope entry (replace semantics).
|
|
1501
|
+
B.startBlock(finExcLabel);
|
|
1502
|
+
emitter.declare(`declare ptr @scr_exc_take()`);
|
|
1503
|
+
emitter.declare(`declare void @scr_rethrow(ptr)`);
|
|
1504
|
+
emitter.declare(`declare void @scr_caught_release(ptr)`);
|
|
1505
|
+
const stash = B.tmp();
|
|
1506
|
+
const stashSlot = B.slot();
|
|
1507
|
+
B.entryAllocas.push(`${stashSlot} = alloca ptr ; finally exception stash`);
|
|
1508
|
+
B.line(`${stash} = call ptr @scr_exc_take() ; stash across finally`);
|
|
1509
|
+
B.line(`store ptr ${stash}, ptr ${stashSlot}`);
|
|
1510
|
+
emitter.scopes.push([{ slot: stashSlot, type: CAUGHT }]);
|
|
1511
|
+
const suppressHandler = s.suppressFinallyErrors || s.dropFinallyErrors
|
|
1512
|
+
? {
|
|
1513
|
+
label: B.newLabel("try.fs"),
|
|
1514
|
+
used: false,
|
|
1515
|
+
frameDepth: emitter.frames.length,
|
|
1516
|
+
scopeDepth: emitter.scopes.length,
|
|
1517
|
+
}
|
|
1518
|
+
: null;
|
|
1519
|
+
if (suppressHandler)
|
|
1520
|
+
emitter.tryStack.push(suppressHandler);
|
|
1521
|
+
emitter.emitBlock(s.finallyBody);
|
|
1522
|
+
if (suppressHandler)
|
|
1523
|
+
emitter.tryStack.pop();
|
|
1524
|
+
emitter.scopes.pop(); // normal completion keeps the stash for the re-raise
|
|
1525
|
+
B.line(`call void @scr_rethrow(ptr ${stash})`);
|
|
1526
|
+
B.line(`call void @scr_caught_release(ptr ${stash})`);
|
|
1527
|
+
emitter.emitUnwind();
|
|
1528
|
+
if (suppressHandler?.used) {
|
|
1529
|
+
B.startBlock(suppressHandler.label);
|
|
1530
|
+
const cleanup = s.dropFinallyErrors ? "scr_exc_keep_first" : "scr_exc_suppress";
|
|
1531
|
+
emitter.declare(`declare void @${cleanup}(ptr)`);
|
|
1532
|
+
B.line(`call void @${cleanup}(ptr ${stash}) ; consumes stash`);
|
|
1533
|
+
emitter.emitUnwind();
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
B.startBlock(endLabel);
|
|
1537
|
+
}
|
|
1538
|
+
else {
|
|
1539
|
+
B.startBlock(endLabel);
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
/** JS-exact switch: lazily evaluated, arbitrary-expression case tests in
|
|
1543
|
+
* source order, bodies falling through in source order until a break —
|
|
1544
|
+
* Literal-only tests can use native dispatch; other tests keep a chain
|
|
1545
|
+
* of conditional branches. All case bodies
|
|
1546
|
+
* share ONE scope; because dispatch can jump PAST a varDecl into a later
|
|
1547
|
+
* case, refcounted/boxed case-body locals are NULL-reset up front and
|
|
1548
|
+
* the scope-exit releases rely on NULL tolerance. */
|
|
1549
|
+
export function emitSwitch(emitter, s) {
|
|
1550
|
+
const unitSwitch = charAtUnitSwitch(s);
|
|
1551
|
+
if (unitSwitch !== null)
|
|
1552
|
+
return emitSwitch(emitter, unitSwitch);
|
|
1553
|
+
const B = emitter.B;
|
|
1554
|
+
const discKind = s.disc.type.kind;
|
|
1555
|
+
if (discKind !== "f64" && discKind !== "string" && discKind !== "bool") {
|
|
1556
|
+
throw new LlvmUnsupportedError(`switch:${discKind}`, s.loc);
|
|
1557
|
+
}
|
|
1558
|
+
// The disc temp lives in the whole statement's frame: for a string
|
|
1559
|
+
// discriminant it stays alive across every test and body, released
|
|
1560
|
+
// when the switch statement ends (break lands past this statement's
|
|
1561
|
+
// frame release — releaseForJump keeps the target's own frame).
|
|
1562
|
+
const disc = emitter.emitExpr(s.disc);
|
|
1563
|
+
for (const c of s.cases) {
|
|
1564
|
+
for (const stmt of c.body) {
|
|
1565
|
+
if (stmt.kind !== "varDecl")
|
|
1566
|
+
continue;
|
|
1567
|
+
const local = emitter.currentLocals.get(stmt.localId);
|
|
1568
|
+
if (local.boxed || isRefCounted(local.type)) {
|
|
1569
|
+
B.line(`store ptr null, ptr %${mangleLocal(local.id)} ; case-scoped ${local.name}`);
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
const end = B.newLabel("sw.e");
|
|
1574
|
+
const caseLabels = s.cases.map(() => B.newLabel("sw.c"));
|
|
1575
|
+
const defaultIdx = s.cases.findIndex((c) => c.test === null);
|
|
1576
|
+
const fallback = defaultIdx >= 0 ? caseLabels[defaultIdx] : end;
|
|
1577
|
+
const nullableString = nullableStringSwitch(emitter, s);
|
|
1578
|
+
if (nullableString !== null) {
|
|
1579
|
+
// `undefined` matches no string literal; any other value is the
|
|
1580
|
+
// string itself and dispatches as a string switch.
|
|
1581
|
+
const value = emitter.emitExpr(nullableString.value);
|
|
1582
|
+
const present = B.tmp();
|
|
1583
|
+
const dispatch = B.newLabel("sw.string");
|
|
1584
|
+
B.line(`${present} = icmp ne ptr ${value.name}, null`);
|
|
1585
|
+
B.condBr(present, dispatch, fallback);
|
|
1586
|
+
B.startBlock(dispatch);
|
|
1587
|
+
const text = { name: value.name, type: STRING };
|
|
1588
|
+
if (!emitLiteralSwitch(emitter, text, undefined, nullableString.cases, caseLabels, fallback)) {
|
|
1589
|
+
nullableString.cases.forEach((c, i) => {
|
|
1590
|
+
if (c.test?.kind !== "strLit")
|
|
1591
|
+
return;
|
|
1592
|
+
const hit = B.tmp();
|
|
1593
|
+
B.line(`${hit} = call zeroext i1 ${emitter.literalEquals(c.test.value)}(ptr ${value.name})`);
|
|
1594
|
+
const next = B.newLabel("sw.t");
|
|
1595
|
+
B.condBr(hit, caseLabels[i], next);
|
|
1596
|
+
B.startBlock(next);
|
|
1597
|
+
});
|
|
1598
|
+
B.br(fallback);
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
else if (!emitLiteralSwitch(emitter, disc, s.disc, s.cases, caseLabels, fallback)) {
|
|
1602
|
+
s.cases.forEach((c, i) => {
|
|
1603
|
+
if (c.test === null)
|
|
1604
|
+
return;
|
|
1605
|
+
// Lazy source-order test evaluation (a test after the match never
|
|
1606
|
+
// runs). Each test's temps release right after its comparison.
|
|
1607
|
+
emitter.frames.push([]);
|
|
1608
|
+
const t = emitter.emitExpr(c.test);
|
|
1609
|
+
const hit = B.tmp();
|
|
1610
|
+
if (c.test.kind === "strLit") {
|
|
1611
|
+
B.line(`${hit} = call zeroext i1 ${emitter.literalEquals(c.test.value)}(ptr ${disc.name})`);
|
|
1612
|
+
}
|
|
1613
|
+
else if (c.test.type.kind === "string") {
|
|
1614
|
+
emitter.declare(`declare zeroext i1 @scr_str_eq(ptr, ptr)`);
|
|
1615
|
+
B.line(`${hit} = call zeroext i1 @sc_str_eq(ptr ${disc.name}, ptr ${t.name})`);
|
|
1616
|
+
}
|
|
1617
|
+
else if (c.test.type.kind === "bool") {
|
|
1618
|
+
B.line(`${hit} = icmp eq i1 ${disc.name}, ${t.name}`);
|
|
1619
|
+
}
|
|
1620
|
+
else {
|
|
1621
|
+
B.line(`${hit} = fcmp oeq double ${disc.name}, ${t.name}`);
|
|
1622
|
+
}
|
|
1623
|
+
emitter.releaseTemps(emitter.frames.pop());
|
|
1624
|
+
const next = B.newLabel("sw.t");
|
|
1625
|
+
B.condBr(hit, caseLabels[i], next);
|
|
1626
|
+
B.startBlock(next);
|
|
1627
|
+
});
|
|
1628
|
+
B.br(fallback);
|
|
1629
|
+
}
|
|
1630
|
+
emitter.jumpTargets.push({
|
|
1631
|
+
kind: "switch",
|
|
1632
|
+
brkLabel: end,
|
|
1633
|
+
contLabel: null,
|
|
1634
|
+
labels: s.labels,
|
|
1635
|
+
frameDepth: emitter.frames.length,
|
|
1636
|
+
scopeDepth: emitter.scopes.length,
|
|
1637
|
+
finallyDepth: emitter.finallyStack.length,
|
|
1638
|
+
});
|
|
1639
|
+
const scope = [];
|
|
1640
|
+
emitter.scopes.push(scope);
|
|
1641
|
+
s.cases.forEach((c, i) => {
|
|
1642
|
+
B.br(caseLabels[i]); // the previous body's natural fall-through
|
|
1643
|
+
B.startBlock(caseLabels[i]);
|
|
1644
|
+
emitter.emitStmts(c.body);
|
|
1645
|
+
});
|
|
1646
|
+
emitter.jumpTargets.pop();
|
|
1647
|
+
emitter.scopes.pop();
|
|
1648
|
+
// Natural fall-off of the last body releases the shared scope; a jump
|
|
1649
|
+
// already released it before jumping.
|
|
1650
|
+
const lastBody = s.cases[s.cases.length - 1]?.body;
|
|
1651
|
+
if (!lastBody || !endsWithJump(lastBody))
|
|
1652
|
+
emitter.releaseScope(scope);
|
|
1653
|
+
B.br(end);
|
|
1654
|
+
B.startBlock(end);
|
|
1655
|
+
}
|
|
1656
|
+
/** Emit a loop's condition, body and update through `emitCopy`, twice
|
|
1657
|
+
* when speculative-integers.ts plans a fast integer copy. Both copies
|
|
1658
|
+
* share the loop's setup and exit; the ordinary copy comes first so the
|
|
1659
|
+
* fast copy is only emitted when every resume point exists. */
|
|
1660
|
+
export function emitLoopCopies(emitter, loop, allowed, exit, emitCopy) {
|
|
1661
|
+
const plan = allowed &&
|
|
1662
|
+
emitter.speculativeLoopsEnabled &&
|
|
1663
|
+
emitter.speculation === null &&
|
|
1664
|
+
emitter.speculationResume === null
|
|
1665
|
+
? planSpeculativeLoop(loop, (id) => emitter.speculativeLocal(id), (id) => emitter.integerLoopBindings.has(id) || emitter.int32Locals.has(id), (e) => {
|
|
1666
|
+
const range = emitter.integerRanges.get(e);
|
|
1667
|
+
return (range !== undefined &&
|
|
1668
|
+
range !== null &&
|
|
1669
|
+
range.min >= -Number.MAX_SAFE_INTEGER &&
|
|
1670
|
+
range.max <= Number.MAX_SAFE_INTEGER);
|
|
1671
|
+
}, (id) => emitter.speculativeLocal(id) || emitter.speculativeInvariantGlobal(id))
|
|
1672
|
+
: null;
|
|
1673
|
+
if (!plan) {
|
|
1674
|
+
emitCopy(exit);
|
|
1675
|
+
return;
|
|
1676
|
+
}
|
|
1677
|
+
const B = emitter.B;
|
|
1678
|
+
const entries = new Map();
|
|
1679
|
+
let ok = "true";
|
|
1680
|
+
for (const [id, live] of plan.locals) {
|
|
1681
|
+
if (!live)
|
|
1682
|
+
continue;
|
|
1683
|
+
const value = B.tmp();
|
|
1684
|
+
B.line(`${value} = load double, ptr ${emitter.binding(id).slot}`);
|
|
1685
|
+
const [integer, exact] = emitSafeIntegerCheck(emitter, value);
|
|
1686
|
+
entries.set(id, integer);
|
|
1687
|
+
if (ok === "true")
|
|
1688
|
+
ok = exact;
|
|
1689
|
+
else {
|
|
1690
|
+
const both = B.tmp();
|
|
1691
|
+
B.line(`${both} = and i1 ${ok}, ${exact}`);
|
|
1692
|
+
ok = both;
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
const fast = B.newLabel("spec.fast"), slow = B.newLabel("spec.slow");
|
|
1696
|
+
B.condBr(ok, fast, slow);
|
|
1697
|
+
const resume = new Map();
|
|
1698
|
+
for (const s of plan.writes)
|
|
1699
|
+
resume.set(s, { label: B.newLabel("spec.resume"), placed: false });
|
|
1700
|
+
B.startBlock(slow);
|
|
1701
|
+
emitter.speculationResume = resume;
|
|
1702
|
+
try {
|
|
1703
|
+
emitCopy(exit);
|
|
1704
|
+
}
|
|
1705
|
+
finally {
|
|
1706
|
+
emitter.speculationResume = null;
|
|
1707
|
+
}
|
|
1708
|
+
B.startBlock(fast);
|
|
1709
|
+
if (![...resume.values()].every((r) => r.placed)) {
|
|
1710
|
+
B.br(slow);
|
|
1711
|
+
return;
|
|
1712
|
+
}
|
|
1713
|
+
for (const id of plan.locals.keys()) {
|
|
1714
|
+
const shadow = B.slot();
|
|
1715
|
+
B.entryAllocas.push(`${shadow} = alloca i64 ; speculative integer ${emitter.currentLocals.get(id)?.name ?? id}`);
|
|
1716
|
+
const entry = entries.get(id);
|
|
1717
|
+
if (entry !== undefined) {
|
|
1718
|
+
// The same double, now visibly an integer conversion: the double
|
|
1719
|
+
// phis of the fast copy fold into integer phis.
|
|
1720
|
+
const exact = B.tmp();
|
|
1721
|
+
B.line(`store i64 ${entry}, ptr ${shadow}`);
|
|
1722
|
+
B.line(`${exact} = sitofp i64 ${entry} to double`);
|
|
1723
|
+
B.line(`store double ${exact}, ptr ${emitter.binding(id).slot}`);
|
|
1724
|
+
}
|
|
1725
|
+
else
|
|
1726
|
+
B.line(`store i64 0, ptr ${shadow}`);
|
|
1727
|
+
emitter.integerLoopBindings.set(id, {
|
|
1728
|
+
slot: shadow,
|
|
1729
|
+
type: "i64",
|
|
1730
|
+
signed: true,
|
|
1731
|
+
range: SPECULATIVE_RANGE,
|
|
1732
|
+
});
|
|
1733
|
+
}
|
|
1734
|
+
// A global's store stays in the loop (calls may read it). When nothing
|
|
1735
|
+
// in the loop can observe it, its double is written once on leaving the
|
|
1736
|
+
// copy instead, so the loop keeps it in a register as the double copy
|
|
1737
|
+
// would.
|
|
1738
|
+
const deferred = new Set();
|
|
1739
|
+
// Worker loops also leave through their cancellation poll.
|
|
1740
|
+
if (plan.observerFree && !emitter.mod.workers)
|
|
1741
|
+
for (const s of plan.writes) {
|
|
1742
|
+
const id = speculativeWriteTarget(s).localId;
|
|
1743
|
+
if (!emitter.currentLocals.has(id))
|
|
1744
|
+
deferred.add(id);
|
|
1745
|
+
}
|
|
1746
|
+
emitter.speculation = {
|
|
1747
|
+
writes: plan.writes,
|
|
1748
|
+
resume: new Map([...resume].map(([s, r]) => [s, r.label])),
|
|
1749
|
+
deferred,
|
|
1750
|
+
};
|
|
1751
|
+
try {
|
|
1752
|
+
if (deferred.size === 0)
|
|
1753
|
+
emitCopy(exit);
|
|
1754
|
+
else {
|
|
1755
|
+
const leave = B.newLabel("spec.leave");
|
|
1756
|
+
emitCopy(leave);
|
|
1757
|
+
B.startBlock(leave);
|
|
1758
|
+
emitter.writeBackSpeculativeGlobals(deferred);
|
|
1759
|
+
B.br(exit);
|
|
1760
|
+
}
|
|
1761
|
+
}
|
|
1762
|
+
finally {
|
|
1763
|
+
emitter.speculation = null;
|
|
1764
|
+
for (const id of plan.locals.keys())
|
|
1765
|
+
emitter.integerLoopBindings.delete(id);
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
/** A speculated write in the fast copy: compute the value as a safe
|
|
1769
|
+
* integer, store it to the shadow and its exact double to the local.
|
|
1770
|
+
* Any failed check re-executes the statement in the ordinary copy. */
|
|
1771
|
+
export function emitSpeculativeWrite(emitter, s, resume) {
|
|
1772
|
+
const B = emitter.B;
|
|
1773
|
+
const target = speculativeWriteTarget(s);
|
|
1774
|
+
const binding = emitter.integerLoopBindings.get(target.localId);
|
|
1775
|
+
const failed = B.newLabel("spec.bail");
|
|
1776
|
+
let bails = false;
|
|
1777
|
+
emitter.declare("declare i1 @llvm.expect.i1(i1, i1)");
|
|
1778
|
+
const bail = (condition) => {
|
|
1779
|
+
if (condition === "false")
|
|
1780
|
+
return;
|
|
1781
|
+
bails = true;
|
|
1782
|
+
const expected = B.tmp();
|
|
1783
|
+
B.line(`${expected} = call i1 @llvm.expect.i1(i1 ${condition}, i1 false)`);
|
|
1784
|
+
const next = B.newLabel("spec.ok");
|
|
1785
|
+
B.condBr(expected, failed, next);
|
|
1786
|
+
B.startBlock(next);
|
|
1787
|
+
};
|
|
1788
|
+
// Heap reads come first, before any check, and release their temporaries
|
|
1789
|
+
// at once: a bailing path then owns nothing, and reads have no effect
|
|
1790
|
+
// whose reordering before the arithmetic could be observed.
|
|
1791
|
+
const reads = new Map();
|
|
1792
|
+
if (target.value !== null) {
|
|
1793
|
+
emitter.frames.push([]);
|
|
1794
|
+
for (const read of speculativeReads(target.value))
|
|
1795
|
+
reads.set(read, emitter.emitExpr(read));
|
|
1796
|
+
emitter.releaseTemps(emitter.frames.pop());
|
|
1797
|
+
}
|
|
1798
|
+
emitter.frames.push([]);
|
|
1799
|
+
let result;
|
|
1800
|
+
if (target.value === null) {
|
|
1801
|
+
const old = B.tmp();
|
|
1802
|
+
result = B.tmp();
|
|
1803
|
+
B.line(`${old} = load i64, ptr ${binding.slot}`);
|
|
1804
|
+
B.line(`${result} = ${target.op === "+" ? "add" : "sub"} nsw i64 ${old}, 1`);
|
|
1805
|
+
const biased = B.tmp(), outside = B.tmp();
|
|
1806
|
+
B.line(`${biased} = add i64 ${result}, ${Number.MAX_SAFE_INTEGER}`);
|
|
1807
|
+
B.line(`${outside} = icmp ugt i64 ${biased}, ${2 * Number.MAX_SAFE_INTEGER}`);
|
|
1808
|
+
bail(outside);
|
|
1809
|
+
}
|
|
1810
|
+
else
|
|
1811
|
+
result = emitSpeculativeInteger(emitter, target.value, bail, reads);
|
|
1812
|
+
// Speculable values read only numbers past this point.
|
|
1813
|
+
if (emitter.frames.pop().length > 0)
|
|
1814
|
+
throw new InternalCompilerError("llvm emitter bug: speculative write owns a temporary");
|
|
1815
|
+
B.line(`store i64 ${result}, ptr ${binding.slot}`);
|
|
1816
|
+
const deferred = emitter.speculation.deferred;
|
|
1817
|
+
if (!deferred.has(target.localId)) {
|
|
1818
|
+
const number = B.tmp();
|
|
1819
|
+
B.line(`${number} = sitofp i64 ${result} to double`);
|
|
1820
|
+
B.line(`store double ${number}, ptr ${emitter.binding(target.localId).slot}`);
|
|
1821
|
+
}
|
|
1822
|
+
if (!bails)
|
|
1823
|
+
return;
|
|
1824
|
+
const done = B.newLabel("spec.done");
|
|
1825
|
+
B.br(done);
|
|
1826
|
+
B.startBlock(failed);
|
|
1827
|
+
emitter.writeBackSpeculativeGlobals(deferred);
|
|
1828
|
+
B.br(resume);
|
|
1829
|
+
B.startBlock(done);
|
|
1830
|
+
}
|
|
1831
|
+
/**
|
|
1832
|
+
* Lower canonical `target = target + suffix` after evaluating the old
|
|
1833
|
+
* left side and suffix in JavaScript order. The snapshot stays owned by
|
|
1834
|
+
* the statement frame while the destination relinquishes its CURRENT
|
|
1835
|
+
* value, making the snapshot unique unless a real observable alias exists.
|
|
1836
|
+
*/
|
|
1837
|
+
export function emitStringSelfConcatAssign(emitter, localId, left, suffix, retainForYield) {
|
|
1838
|
+
const moved = emitter.emitMovedSelfConcat(localId, left, suffix, retainForYield);
|
|
1839
|
+
if (moved)
|
|
1840
|
+
return moved;
|
|
1841
|
+
const snapshot = emitter.emitExpr(left);
|
|
1842
|
+
// A suffix of several parts, or a number, appends each operand to the
|
|
1843
|
+
// snapshot directly (in place once the binding lets go of it) instead
|
|
1844
|
+
// of first building the suffix as a separate string.
|
|
1845
|
+
const parts = stringParts(suffix);
|
|
1846
|
+
const mixed = parts.length > 1 || numberPart(parts[0]) !== null;
|
|
1847
|
+
const charCode = mixed ? null : emitter.emitSingleCharCode(suffix);
|
|
1848
|
+
const inputs = mixed ? emitConcatInputs(emitter, parts) : [];
|
|
1849
|
+
// The concat only reads the suffix; relinquishing the binding below
|
|
1850
|
+
// runs no code that could rebind a borrowed local.
|
|
1851
|
+
const right = mixed || charCode !== null ? null : emitStringInputs(emitter, [suffix])[0];
|
|
1852
|
+
const b = emitter.binding(localId);
|
|
1853
|
+
const B = emitter.B;
|
|
1854
|
+
if (b.kind === "boxed") {
|
|
1855
|
+
// set_ref(NULL) unlinks then releases the binding's post-suffix value.
|
|
1856
|
+
emitter.boxSet(emitter.loadBox(b.slot), b.type, "null");
|
|
1857
|
+
}
|
|
1858
|
+
else {
|
|
1859
|
+
const old = B.tmp();
|
|
1860
|
+
B.line(`${old} = load ptr, ptr ${b.slot}`);
|
|
1861
|
+
B.line(`store ptr null, ptr ${b.slot}`);
|
|
1862
|
+
if (b.kind === "global")
|
|
1863
|
+
emitter.releaseHeap(old, b.type);
|
|
1864
|
+
else
|
|
1865
|
+
emitter.releaseFrame(old, b.type);
|
|
1866
|
+
}
|
|
1867
|
+
let raw;
|
|
1868
|
+
if (charCode !== null) {
|
|
1869
|
+
// The snapshot moves into the consuming character append.
|
|
1870
|
+
emitter.toFrame(snapshot);
|
|
1871
|
+
emitter.declare(`declare ptr @scr_str_concat_move_char_code(ptr, double)`);
|
|
1872
|
+
raw = B.tmp();
|
|
1873
|
+
B.line(`${raw} = call ptr @scr_str_concat_move_char_code(ptr ${snapshot.name}, double ${charCode.name})`);
|
|
1874
|
+
}
|
|
1875
|
+
else if (right === null) {
|
|
1876
|
+
raw = emitMixedConcat(emitter, snapshot.name, inputs);
|
|
1877
|
+
}
|
|
1878
|
+
else {
|
|
1879
|
+
emitter.declare(`declare ptr @scr_str_concat(ptr, ptr)`);
|
|
1880
|
+
raw = B.tmp();
|
|
1881
|
+
B.line(`${raw} = call ptr @scr_str_concat(ptr ${snapshot.name}, ptr ${right.name})`);
|
|
1882
|
+
}
|
|
1883
|
+
const result = emitter.own({ name: raw, type: left.type });
|
|
1884
|
+
if (retainForYield) {
|
|
1885
|
+
const stored = b.kind === "local"
|
|
1886
|
+
? emitter.retainFrame(result.name, result.type)
|
|
1887
|
+
: emitter.retainHeap(result.name, result.type);
|
|
1888
|
+
if (b.kind === "boxed")
|
|
1889
|
+
emitter.boxSet(emitter.loadBox(b.slot), b.type, stored);
|
|
1890
|
+
else
|
|
1891
|
+
B.line(`store ptr ${stored}, ptr ${b.slot}`);
|
|
1892
|
+
}
|
|
1893
|
+
else {
|
|
1894
|
+
if (b.kind === "local")
|
|
1895
|
+
emitter.toFrame(result);
|
|
1896
|
+
else
|
|
1897
|
+
emitter.toHeap(result);
|
|
1898
|
+
if (b.kind === "boxed")
|
|
1899
|
+
emitter.boxSet(emitter.loadBox(b.slot), b.type, result.name);
|
|
1900
|
+
else
|
|
1901
|
+
B.line(`store ptr ${result.name}, ptr ${b.slot}`);
|
|
1902
|
+
}
|
|
1903
|
+
return result;
|
|
1904
|
+
}
|
|
1905
|
+
/** `switch (x)` on a `string | undefined` value whose case tests are all
|
|
1906
|
+
* string literals: the frontend's `switch (true)` over `x === "lit"` union
|
|
1907
|
+
* equalities against one switch local. The local and the cases with plain
|
|
1908
|
+
* string literal tests. */
|
|
1909
|
+
function nullableStringSwitch(emitter, s) {
|
|
1910
|
+
if (s.disc.kind !== "boolLit" || !s.disc.value)
|
|
1911
|
+
return null;
|
|
1912
|
+
let value = null;
|
|
1913
|
+
const cases = [];
|
|
1914
|
+
for (const c of s.cases) {
|
|
1915
|
+
const test = c.test;
|
|
1916
|
+
if (test === null) {
|
|
1917
|
+
cases.push(c);
|
|
1918
|
+
continue;
|
|
1919
|
+
}
|
|
1920
|
+
if (test.kind !== "unionEq" ||
|
|
1921
|
+
test.negated ||
|
|
1922
|
+
test.sameValue ||
|
|
1923
|
+
test.left.kind !== "varRef" ||
|
|
1924
|
+
test.right.kind !== "unionWrap" ||
|
|
1925
|
+
test.right.value.kind !== "strLit")
|
|
1926
|
+
return null;
|
|
1927
|
+
const nullable = emitter.nullableUnions.get(test.unionId);
|
|
1928
|
+
if (nullable === null ||
|
|
1929
|
+
nullable.repr !== "single" ||
|
|
1930
|
+
nullable.nullTag !== -1 ||
|
|
1931
|
+
nullable.arm.kind !== "string" ||
|
|
1932
|
+
test.right.tag !== nullable.refTag)
|
|
1933
|
+
return null;
|
|
1934
|
+
if (value !== null && value.localId !== test.left.localId)
|
|
1935
|
+
return null;
|
|
1936
|
+
value = test.left;
|
|
1937
|
+
cases.push({ ...c, test: test.right.value });
|
|
1938
|
+
}
|
|
1939
|
+
return value === null ? null : { value, cases };
|
|
1940
|
+
}
|
|
1941
|
+
/** `switch (s.charAt(i))` (or `switch (s[i])`) whose case tests are all
|
|
1942
|
+
* one-unit string literals, as a switch on `s.charCodeAt(i)` with the units
|
|
1943
|
+
* as cases: no character string is built. An index out of range answers
|
|
1944
|
+
* NaN, which matches no case, as "" matches no one-unit literal. */
|
|
1945
|
+
function charAtUnitSwitch(s) {
|
|
1946
|
+
const disc = s.disc;
|
|
1947
|
+
if (disc.kind !== "strIntrinsic" || disc.method !== "charAt" || disc.args.length !== 1)
|
|
1948
|
+
return null;
|
|
1949
|
+
if (!s.cases.some((c) => c.test !== null))
|
|
1950
|
+
return null;
|
|
1951
|
+
if (!s.cases.every((c) => c.test === null || (c.test.kind === "strLit" && c.test.value.length === 1)))
|
|
1952
|
+
return null;
|
|
1953
|
+
return {
|
|
1954
|
+
...s,
|
|
1955
|
+
disc: { ...disc, method: "charCodeAt", type: F64 },
|
|
1956
|
+
cases: s.cases.map((c) => c.test?.kind === "strLit"
|
|
1957
|
+
? {
|
|
1958
|
+
...c,
|
|
1959
|
+
test: { kind: "numLit", value: c.test.value.charCodeAt(0), type: F64, loc: c.test.loc },
|
|
1960
|
+
}
|
|
1961
|
+
: c),
|
|
1962
|
+
};
|
|
1963
|
+
}
|
|
1964
|
+
//# sourceMappingURL=emit-statements.js.map
|