@scriptc/compiler 0.3.1 → 0.3.3
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 +832 -55
- package/dist/backend/cycle-analysis.js +6 -1
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/executable-features.js +1 -0
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/literals.d.ts +7 -0
- package/dist/backend/literals.js +32 -0
- package/dist/backend/literals.js.map +1 -1
- package/dist/backend/literals.test.js +17 -1
- package/dist/backend/literals.test.js.map +1 -1
- package/dist/backend/llvm/alloc.d.ts +15 -4
- package/dist/backend/llvm/alloc.js +63 -25
- package/dist/backend/llvm/alloc.js.map +1 -1
- package/dist/backend/llvm/alloc.test.js +62 -2
- package/dist/backend/llvm/alloc.test.js.map +1 -1
- package/dist/backend/llvm/appended-array-literals.d.ts +2 -0
- package/dist/backend/llvm/appended-array-literals.js +109 -0
- package/dist/backend/llvm/appended-array-literals.js.map +1 -0
- package/dist/backend/llvm/appended-array-literals.test.d.ts +1 -0
- package/dist/backend/llvm/appended-array-literals.test.js +90 -0
- package/dist/backend/llvm/appended-array-literals.test.js.map +1 -0
- package/dist/backend/llvm/array-search.d.ts +8 -0
- package/dist/backend/llvm/array-search.js +52 -0
- package/dist/backend/llvm/array-search.js.map +1 -0
- package/dist/backend/llvm/array-search.test.d.ts +1 -0
- package/dist/backend/llvm/array-search.test.js +72 -0
- package/dist/backend/llvm/array-search.test.js.map +1 -0
- package/dist/backend/llvm/call-lifetimes.d.ts +11 -1
- package/dist/backend/llvm/call-lifetimes.js +74 -4
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +54 -0
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/classes.js +97 -38
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/classes.test.js +2 -2
- package/dist/backend/llvm/common.d.ts +1 -1
- package/dist/backend/llvm/common.js +1 -1
- package/dist/backend/llvm/dense-array-access.d.ts +5 -0
- package/dist/backend/llvm/dense-array-access.js +18 -13
- package/dist/backend/llvm/dense-array-access.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.test.js +15 -2
- package/dist/backend/llvm/dense-array-access.test.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +6 -0
- package/dist/backend/llvm/dyn.js +84 -11
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +108 -16
- package/dist/backend/llvm/emitter.js +598 -108
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.test.js +26 -3
- package/dist/backend/llvm/emitter.test.js.map +1 -1
- package/dist/backend/llvm/expr-async.js +174 -7
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.js +11 -0
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.d.ts +8 -0
- package/dist/backend/llvm/expr-callbacks.js +96 -2
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.d.ts +12 -1
- package/dist/backend/llvm/expr-calls.js +133 -54
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.d.ts +7 -0
- package/dist/backend/llvm/expr-containers.js +80 -22
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-context.d.ts +2 -0
- package/dist/backend/llvm/expr-control.d.ts +8 -0
- package/dist/backend/llvm/expr-control.js +103 -69
- package/dist/backend/llvm/expr-control.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +21 -10
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.d.ts +7 -0
- package/dist/backend/llvm/expr-primitives.js +53 -51
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-records.js +19 -5
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.d.ts +8 -0
- package/dist/backend/llvm/expr-stream-bridges.js +111 -39
- package/dist/backend/llvm/expr-stream-bridges.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.test.js +49 -1
- package/dist/backend/llvm/expr-stream-bridges.test.js.map +1 -1
- package/dist/backend/llvm/expr-stream-callbacks.d.ts +13 -2
- package/dist/backend/llvm/expr-stream-callbacks.js +80 -5
- package/dist/backend/llvm/expr-stream-callbacks.js.map +1 -1
- package/dist/backend/llvm/inline-unions.d.ts +48 -0
- package/dist/backend/llvm/inline-unions.js +134 -0
- package/dist/backend/llvm/inline-unions.js.map +1 -0
- package/dist/backend/llvm/inline-unions.test.d.ts +1 -0
- package/dist/backend/llvm/inline-unions.test.js +124 -0
- package/dist/backend/llvm/inline-unions.test.js.map +1 -0
- package/dist/backend/llvm/int32-abi.d.ts +18 -2
- package/dist/backend/llvm/int32-abi.js +23 -2
- package/dist/backend/llvm/int32-abi.js.map +1 -1
- package/dist/backend/llvm/int32-abi.test.js +75 -1
- package/dist/backend/llvm/int32-abi.test.js.map +1 -1
- package/dist/backend/llvm/integer-remainder.d.ts +28 -5
- package/dist/backend/llvm/integer-remainder.js +80 -9
- package/dist/backend/llvm/integer-remainder.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +170 -28
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +181 -5
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-network.js +9 -6
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +2 -2
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +208 -9
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +97 -0
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +12 -6
- package/dist/backend/llvm/local-array-reads.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.test.js +6 -3
- package/dist/backend/llvm/local-array-reads.test.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.d.ts +26 -2
- package/dist/backend/llvm/local-union-storage.js +132 -12
- package/dist/backend/llvm/local-union-storage.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.test.js +107 -1
- package/dist/backend/llvm/local-union-storage.test.js.map +1 -1
- package/dist/backend/llvm/loop-array-borrows.d.ts +8 -2
- package/dist/backend/llvm/loop-array-borrows.js +93 -13
- package/dist/backend/llvm/loop-array-borrows.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.d.ts +20 -0
- package/dist/backend/llvm/map-number-lookup.js +66 -0
- package/dist/backend/llvm/map-number-lookup.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.test.d.ts +1 -0
- package/dist/backend/llvm/map-number-lookup.test.js +102 -0
- package/dist/backend/llvm/map-number-lookup.test.js.map +1 -0
- package/dist/backend/llvm/map-read-lifetimes.js +1 -0
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/publish.d.ts +4 -0
- package/dist/backend/llvm/publish.js +3 -1
- package/dist/backend/llvm/publish.js.map +1 -1
- package/dist/backend/llvm/record-results.d.ts +29 -0
- package/dist/backend/llvm/record-results.js +260 -0
- package/dist/backend/llvm/record-results.js.map +1 -0
- package/dist/backend/llvm/reference-effects.js +15 -0
- package/dist/backend/llvm/reference-effects.js.map +1 -1
- package/dist/backend/llvm/reference-writes.js +29 -9
- package/dist/backend/llvm/reference-writes.js.map +1 -1
- package/dist/backend/llvm/regions.d.ts +68 -0
- package/dist/backend/llvm/regions.js +314 -0
- package/dist/backend/llvm/regions.js.map +1 -0
- package/dist/backend/llvm/regions.test.d.ts +1 -0
- package/dist/backend/llvm/regions.test.js +173 -0
- package/dist/backend/llvm/regions.test.js.map +1 -0
- package/dist/backend/llvm/serialized-ir-emission.test.js +2 -0
- package/dist/backend/llvm/serialized-ir-emission.test.js.map +1 -1
- package/dist/backend/llvm/shapes.d.ts +86 -13
- package/dist/backend/llvm/shapes.js +208 -54
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +68 -9
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/split-loops.js +1 -1
- package/dist/backend/llvm/split-loops.js.map +1 -1
- package/dist/backend/llvm/stack-objects.d.ts +29 -0
- package/dist/backend/llvm/stack-objects.js +142 -0
- package/dist/backend/llvm/stack-objects.js.map +1 -0
- package/dist/backend/llvm/stack-objects.test.d.ts +1 -0
- package/dist/backend/llvm/stack-objects.test.js +255 -0
- package/dist/backend/llvm/stack-objects.test.js.map +1 -0
- package/dist/backend/llvm/string-reads.d.ts +4 -1
- package/dist/backend/llvm/string-reads.js +89 -9
- package/dist/backend/llvm/string-reads.js.map +1 -1
- package/dist/backend/llvm/switch-dispatch.js +5 -4
- package/dist/backend/llvm/switch-dispatch.js.map +1 -1
- package/dist/backend/llvm/walkers.d.ts +13 -0
- package/dist/backend/llvm/walkers.js +108 -10
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/may-throw.js +10 -4
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +7 -2
- package/dist/backend/native/executable.js +28 -2
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/library.js +1 -1
- 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 +3 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +1 -0
- package/dist/backend/native-link-info-core.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +1 -1
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-core.d.ts +1 -0
- package/dist/backend/runtime-pack-core.js +1 -0
- package/dist/backend/runtime-pack-core.js.map +1 -1
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.test.js +1 -1
- package/dist/backend/target-diagnostics.js +17 -0
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/target-diagnostics.test.js +16 -0
- package/dist/backend/target-diagnostics.test.js.map +1 -1
- package/dist/compat/fetch-profile.js +4 -4
- package/dist/compat/fetch-profile.js.map +1 -1
- package/dist/contracts/check.js +2 -0
- package/dist/contracts/check.js.map +1 -1
- package/dist/coverage/report.js +1 -1
- package/dist/coverage/report.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +6 -5
- package/dist/diagnostics/diagnostic.js +7 -6
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/executable/executable-cache.d.ts +1 -0
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/frontend/builtin-modules.d.ts +1 -1
- package/dist/frontend/builtin-modules.js +1 -0
- package/dist/frontend/builtin-modules.js.map +1 -1
- package/dist/frontend/comptime-node.js +2 -2
- package/dist/frontend/comptime-node.js.map +1 -1
- package/dist/frontend/experimental-import.d.ts +12 -0
- package/dist/frontend/experimental-import.js +63 -0
- package/dist/frontend/experimental-import.js.map +1 -0
- package/dist/frontend/lowering/binding-analysis.d.ts +1 -1
- package/dist/frontend/lowering/binding-analysis.js +1 -1
- package/dist/frontend/lowering/builtin-calls.d.ts +6 -1
- package/dist/frontend/lowering/builtin-calls.js +36 -0
- package/dist/frontend/lowering/builtin-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/arguments.d.ts +4 -0
- package/dist/frontend/lowering/builtins/arguments.js +8 -4
- package/dist/frontend/lowering/builtins/arguments.js.map +1 -1
- package/dist/frontend/lowering/builtins/blob.d.ts +20 -0
- package/dist/frontend/lowering/builtins/blob.js +167 -0
- package/dist/frontend/lowering/builtins/blob.js.map +1 -0
- package/dist/frontend/lowering/builtins/child-process-async.d.ts +2 -2
- package/dist/frontend/lowering/builtins/child-process-async.js +2 -2
- package/dist/frontend/lowering/builtins/child-process-methods.js +1 -1
- package/dist/frontend/lowering/builtins/child-process-methods.js.map +1 -1
- package/dist/frontend/lowering/builtins/child-process-sync.js +1 -1
- package/dist/frontend/lowering/builtins/child-process-sync.js.map +1 -1
- package/dist/frontend/lowering/builtins/compression.js +3 -2
- package/dist/frontend/lowering/builtins/compression.js.map +1 -1
- package/dist/frontend/lowering/builtins/console.d.ts +16 -6
- package/dist/frontend/lowering/builtins/console.js +33 -9
- package/dist/frontend/lowering/builtins/console.js.map +1 -1
- package/dist/frontend/lowering/builtins/crypto.js +415 -120
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.js +20 -0
- package/dist/frontend/lowering/builtins/errors.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.d.ts +10 -0
- package/dist/frontend/lowering/builtins/filesystem-calls.js +89 -1
- package/dist/frontend/lowering/builtins/filesystem-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/filesystem.d.ts +16 -7
- package/dist/frontend/lowering/builtins/filesystem.js +97 -15
- package/dist/frontend/lowering/builtins/filesystem.js.map +1 -1
- package/dist/frontend/lowering/builtins/fs-glob.d.ts +23 -0
- package/dist/frontend/lowering/builtins/fs-glob.js +224 -0
- package/dist/frontend/lowering/builtins/fs-glob.js.map +1 -0
- package/dist/frontend/lowering/builtins/json.d.ts +2 -2
- package/dist/frontend/lowering/builtins/json.js +13 -4
- package/dist/frontend/lowering/builtins/json.js.map +1 -1
- package/dist/frontend/lowering/builtins/key-object.d.ts +13 -0
- package/dist/frontend/lowering/builtins/key-object.js +56 -0
- package/dist/frontend/lowering/builtins/key-object.js.map +1 -0
- package/dist/frontend/lowering/builtins/module-calls.js +60 -12
- package/dist/frontend/lowering/builtins/module-calls.js.map +1 -1
- package/dist/frontend/lowering/builtins/numbers.d.ts +1 -0
- package/dist/frontend/lowering/builtins/numbers.js +17 -0
- package/dist/frontend/lowering/builtins/numbers.js.map +1 -1
- package/dist/frontend/lowering/builtins/operating-system.d.ts +18 -0
- package/dist/frontend/lowering/builtins/operating-system.js +361 -1
- package/dist/frontend/lowering/builtins/operating-system.js.map +1 -1
- package/dist/frontend/lowering/builtins/performance.d.ts +25 -3
- package/dist/frontend/lowering/builtins/performance.js +340 -5
- package/dist/frontend/lowering/builtins/performance.js.map +1 -1
- package/dist/frontend/lowering/builtins/process.d.ts +2 -2
- package/dist/frontend/lowering/builtins/process.js +122 -17
- package/dist/frontend/lowering/builtins/process.js.map +1 -1
- package/dist/frontend/lowering/builtins/promises.js +109 -2
- package/dist/frontend/lowering/builtins/promises.js.map +1 -1
- package/dist/frontend/lowering/builtins/properties.d.ts +0 -7
- package/dist/frontend/lowering/builtins/properties.js +39 -11
- package/dist/frontend/lowering/builtins/properties.js.map +1 -1
- package/dist/frontend/lowering/builtins/readline.d.ts +23 -8
- package/dist/frontend/lowering/builtins/readline.js +266 -90
- package/dist/frontend/lowering/builtins/readline.js.map +1 -1
- package/dist/frontend/lowering/builtins/text-codecs.d.ts +3 -4
- package/dist/frontend/lowering/builtins/text-codecs.js +3 -4
- package/dist/frontend/lowering/builtins/text-codecs.js.map +1 -1
- package/dist/frontend/lowering/builtins/url.d.ts +8 -0
- package/dist/frontend/lowering/builtins/url.js +36 -0
- package/dist/frontend/lowering/builtins/url.js.map +1 -1
- package/dist/frontend/lowering/call-arguments.js +1 -1
- package/dist/frontend/lowering/call-arguments.js.map +1 -1
- package/dist/frontend/lowering/call-signatures.js +20 -2
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/checked-promise-all.d.ts +10 -3
- package/dist/frontend/lowering/checked-promise-all.js +52 -6
- package/dist/frontend/lowering/checked-promise-all.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +8 -3
- package/dist/frontend/lowering/class-dynamic-dispatch.js +159 -32
- package/dist/frontend/lowering/class-dynamic-dispatch.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js +1 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.test.js.map +1 -1
- package/dist/frontend/lowering/class-protocol-dispatch.d.ts +45 -0
- package/dist/frontend/lowering/class-protocol-dispatch.js +516 -0
- package/dist/frontend/lowering/class-protocol-dispatch.js.map +1 -0
- package/dist/frontend/lowering/coercions/structural-plans.js +2 -1
- package/dist/frontend/lowering/coercions/structural-plans.js.map +1 -1
- package/dist/frontend/lowering/coercions/structural.js +3 -3
- package/dist/frontend/lowering/coercions/structural.js.map +1 -1
- package/dist/frontend/lowering/collation-repertoire.js +6 -5
- package/dist/frontend/lowering/collation-repertoire.js.map +1 -1
- package/dist/frontend/lowering/containers/array-callbacks.js +33 -6
- package/dist/frontend/lowering/containers/array-callbacks.js.map +1 -1
- package/dist/frontend/lowering/containers/array-construction.js +8 -4
- package/dist/frontend/lowering/containers/array-construction.js.map +1 -1
- package/dist/frontend/lowering/containers/array-methods.d.ts +0 -7
- package/dist/frontend/lowering/containers/array-methods.js +43 -2
- package/dist/frontend/lowering/containers/array-methods.js.map +1 -1
- package/dist/frontend/lowering/containers/array-pipelines.js +1 -1
- package/dist/frontend/lowering/containers/array-pipelines.js.map +1 -1
- package/dist/frontend/lowering/containers/bytes.js +38 -26
- package/dist/frontend/lowering/containers/bytes.js.map +1 -1
- package/dist/frontend/lowering/containers/for-of.d.ts +1 -1
- package/dist/frontend/lowering/containers/for-of.js +5 -1
- package/dist/frontend/lowering/containers/for-of.js.map +1 -1
- package/dist/frontend/lowering/containers/indexed-objects.js +1 -1
- package/dist/frontend/lowering/containers/indexed-objects.js.map +1 -1
- package/dist/frontend/lowering/containers/string-and-regexp.js +91 -0
- package/dist/frontend/lowering/containers/string-and-regexp.js.map +1 -1
- package/dist/frontend/lowering/crypto-tables.d.ts +3 -3
- package/dist/frontend/lowering/crypto-tables.js +77 -12
- package/dist/frontend/lowering/crypto-tables.js.map +1 -1
- package/dist/frontend/lowering/cycle-initialization.d.ts +18 -2
- package/dist/frontend/lowering/cycle-initialization.js +166 -12
- package/dist/frontend/lowering/cycle-initialization.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.js +7 -2
- package/dist/frontend/lowering/deferred-module-initializers.js.map +1 -1
- package/dist/frontend/lowering/deferred-module-initializers.test.js +28 -0
- package/dist/frontend/lowering/deferred-module-initializers.test.js.map +1 -1
- package/dist/frontend/lowering/expressions/nullish-assignment.js +10 -0
- package/dist/frontend/lowering/expressions/nullish-assignment.js.map +1 -1
- package/dist/frontend/lowering/expressions/object-literals.js +21 -68
- package/dist/frontend/lowering/expressions/object-literals.js.map +1 -1
- package/dist/frontend/lowering/generator-delegation.d.ts +8 -0
- package/dist/frontend/lowering/generator-delegation.js +231 -10
- package/dist/frontend/lowering/generator-delegation.js.map +1 -1
- package/dist/frontend/lowering/generic-functions.d.ts +2 -2
- package/dist/frontend/lowering/generic-functions.js +2 -2
- package/dist/frontend/lowering/generic-functions.js.map +1 -1
- package/dist/frontend/lowering/http2-constants.js +1 -1
- package/dist/frontend/lowering/lifetime-regions.d.ts +11 -0
- package/dist/frontend/lowering/lifetime-regions.js +216 -0
- package/dist/frontend/lowering/lifetime-regions.js.map +1 -0
- package/dist/frontend/lowering/lower-array-sort.d.ts +40 -3
- package/dist/frontend/lowering/lower-array-sort.js +661 -194
- package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
- package/dist/frontend/lowering/lower-array-sort.test.js +103 -4
- package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +2 -2
- package/dist/frontend/lowering/lower-async-iteration.d.ts +6 -3
- package/dist/frontend/lowering/lower-async-iteration.js +248 -2
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +173 -111
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +12 -5
- package/dist/frontend/lowering/lower-classes.js +156 -11
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-comptime.d.ts +1 -1
- package/dist/frontend/lowering/lower-comptime.js +4 -4
- package/dist/frontend/lowering/lower-comptime.js.map +1 -1
- package/dist/frontend/lowering/lower-console.d.ts +13 -0
- package/dist/frontend/lowering/lower-console.js +460 -4
- package/dist/frontend/lowering/lower-console.js.map +1 -1
- package/dist/frontend/lowering/lower-event-emitter.d.ts +6 -0
- package/dist/frontend/lowering/lower-event-emitter.js +124 -38
- package/dist/frontend/lowering/lower-event-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-event-target.d.ts +63 -0
- package/dist/frontend/lowering/lower-event-target.js +362 -0
- package/dist/frontend/lowering/lower-event-target.js.map +1 -0
- package/dist/frontend/lowering/lower-expando.js +2 -2
- package/dist/frontend/lowering/lower-exprs.js +247 -42
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-generators.d.ts +15 -7
- package/dist/frontend/lowering/lower-generators.js +183 -99
- package/dist/frontend/lowering/lower-generators.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.d.ts +8 -1
- package/dist/frontend/lowering/lower-inspect.js +247 -28
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +1 -1
- package/dist/frontend/lowering/lower-modules.js +27 -17
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +2 -2
- package/dist/frontend/lowering/lower-namespaces.js +2 -2
- package/dist/frontend/lowering/lower-server.js +39 -14
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stdlib.d.ts +11 -1
- package/dist/frontend/lowering/lower-stdlib.js +45 -4
- package/dist/frontend/lowering/lower-stdlib.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +2 -2
- package/dist/frontend/lowering/lower-stmts.js +112 -23
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +234 -22
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-timers.js +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +45 -6
- package/dist/frontend/lowering/lowerer.js +360 -48
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/native-ffi.js +2 -2
- package/dist/frontend/lowering/native-ffi.js.map +1 -1
- package/dist/frontend/lowering/regex-span-reads.d.ts +12 -0
- package/dist/frontend/lowering/regex-span-reads.js +164 -0
- package/dist/frontend/lowering/regex-span-reads.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-records.d.ts +115 -0
- package/dist/frontend/lowering/runtime-optional-records.js +715 -0
- package/dist/frontend/lowering/runtime-optional-records.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-records.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-records.test.js +175 -0
- package/dist/frontend/lowering/runtime-optional-records.test.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +7 -3
- package/dist/frontend/lowering/surfaces.js +385 -32
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/var-hoisting.d.ts +3 -0
- package/dist/frontend/lowering/var-hoisting.js +261 -0
- package/dist/frontend/lowering/var-hoisting.js.map +1 -0
- package/dist/frontend/module-syntax.d.ts +1 -1
- package/dist/frontend/module-syntax.js +1 -1
- package/dist/frontend/npm-static-prune.js +1 -1
- package/dist/frontend/npm-static-prune.js.map +1 -1
- package/dist/frontend/npm-static-rewrite-syntax.js +4 -3
- package/dist/frontend/npm-static-rewrite-syntax.js.map +1 -1
- package/dist/frontend/pipeline.js +6 -4
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/program.d.ts +6 -5
- package/dist/frontend/program.js +42 -22
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/program.test.js +13 -0
- package/dist/frontend/program.test.js.map +1 -1
- package/dist/frontend/resolve.js +1 -1
- package/dist/frontend/ts7/adapter.js +1 -1
- package/dist/frontend/ts7/ast-bytes.d.ts +1 -1
- package/dist/frontend/ts7/ast-bytes.js +1 -1
- package/dist/frontend/ts7/semantic-json.d.ts +1 -1
- package/dist/frontend/ts7/semantic-json.js +1 -1
- package/dist/frontend/ts7/semantic-json.js.map +1 -1
- package/dist/frontend/ts7/world-check.js +1 -1
- package/dist/frontend/tsc-codes.js +2 -2
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +28 -1
- package/dist/frontend/type-mapper.js +288 -30
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +12 -6
- package/dist/ir/analysis.js +26 -10
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/analysis.test.js +15 -3
- package/dist/ir/analysis.test.js.map +1 -1
- package/dist/ir/builtin-effects.js +108 -2
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +1 -1
- package/dist/ir/builtin-signatures.js +436 -53
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/function-references.test.js +1 -0
- package/dist/ir/function-references.test.js.map +1 -1
- package/dist/ir/int32-slots.js +2 -0
- package/dist/ir/int32-slots.js.map +1 -1
- package/dist/ir/intrinsic-signatures.js +2 -0
- package/dist/ir/intrinsic-signatures.js.map +1 -1
- package/dist/ir/ir.d.ts +129 -36
- package/dist/ir/ir.js +42 -1
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/runtime-features.d.ts +1 -0
- package/dist/ir/runtime-features.js +116 -5
- package/dist/ir/runtime-features.js.map +1 -1
- package/dist/ir/scalar-records.js +1 -2
- package/dist/ir/scalar-records.js.map +1 -1
- package/dist/ir/serialize.js +1 -1
- package/dist/ir/serialize.js.map +1 -1
- package/dist/ir/traverse.js +1 -0
- package/dist/ir/traverse.js.map +1 -1
- package/dist/ir/validate.js +250 -34
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +125 -0
- package/dist/ir/validate.test.js.map +1 -1
- package/dist/library/fence-eval.d.ts +1 -1
- package/dist/library/fence-eval.js +5 -4
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/ir-policy.js +11 -4
- package/dist/library/ir-policy.js.map +1 -1
- package/dist/library/library-profile.js +13 -13
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/prepare.js +1 -1
- package/dist/library/prepare.js.map +1 -1
- package/dist/library/sidecar.js +3 -3
- package/dist/library/sidecar.js.map +1 -1
- package/dist/native/prepare.js +3 -2
- package/dist/native/prepare.js.map +1 -1
- package/dist/native/sanitizer.test.js +1 -0
- package/dist/native/sanitizer.test.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +537 -142
|
@@ -1,13 +1,15 @@
|
|
|
1
|
+
import { emitArraySearchHelpers } from "./array-search.js";
|
|
2
|
+
import { emitStringInputs } from "./string-lifetimes.js";
|
|
1
3
|
import { emitLlvmLayouts } from "./layouts.js";
|
|
2
4
|
import { compileRegexMatcher } from "./regex-matchers.js";
|
|
3
|
-
import { FIRST_EMITTED_CYC_KIND, inlineAllocSupported } from "./alloc.js";
|
|
4
|
-
import { llvmBytes as llBytes } from "../literals.js";
|
|
5
|
+
import { CYC_BUF, CYC_HDR, FIRST_EMITTED_CYC_KIND, inlineAllocSupported } from "./alloc.js";
|
|
6
|
+
import { hasLoneSurrogate, llvmBytes as llBytes, wtf8Bytes } from "../literals.js";
|
|
5
7
|
import { InternalCompilerError } from "../../errors.js";
|
|
6
8
|
import { createHash } from "node:crypto";
|
|
7
9
|
import { endsWithJump, matchStringSelfConcat, streamTypedRefEligible, undefinedArmTag, } from "../../ir/analysis.js";
|
|
8
10
|
import { emitLibraryIdentityLines } from "../library-identity-markers.js";
|
|
9
11
|
import { loopTestsEveryIteration } from "../loop-polls.js";
|
|
10
|
-
import { CAUGHT, ffiCallbackType, isDynTypedRefType, isFfiContextParam, isRefCounted, isUnitType, POINTER_KINDS, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, typeEquals, typeKey, STRING, VOID, } from "../../ir/ir.js";
|
|
12
|
+
import { CAUGHT, ffiCallbackType, isDynTypedRefType, isFfiContextParam, isRefCounted, isUnitType, POINTER_KINDS, RUNTIME_EMITTER_CLASS, RUNTIME_EVENT_CLASS, RUNTIME_EVENT_TARGET_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, typeEquals, typeKey, STRING, VOID, } from "../../ir/ir.js";
|
|
11
13
|
import { moduleRuntimeFeatures } from "../../ir/runtime-features.js";
|
|
12
14
|
import { matchIntegerArrayForLoop, matchIntegerBytesForLoop, matchIntegerCountedForLoop, } from "../../ir/integer-loops.js";
|
|
13
15
|
import { emitCountedLoopLimit } from "./counted-loops.js";
|
|
@@ -16,6 +18,7 @@ import { findBytesBounds } from "./bytes-bounds.js";
|
|
|
16
18
|
import { emitByteWindowGuard, findInitializedByteLoopBindings, matchByteWindow, } from "./byte-windows.js";
|
|
17
19
|
import { canDeferSplitPiece, emitSplitSpanNext, materializeSplitPiece, emitSplitCursor, emitSplitNext, emitSplitScratch, emitSplitSnapshot, findPrivateSplitLocals, loadSplitSnapshot, storeSplitSnapshot, stringSplit, } from "./split-loops.js";
|
|
18
20
|
import { scalarizeNumericRecords } from "../../ir/scalar-records.js";
|
|
21
|
+
import { RESULT_ENTRY_PREFIX, addRecordResultEntries } from "./record-results.js";
|
|
19
22
|
import { specializeNumericCalls } from "../../ir/numeric-call-specialization.js";
|
|
20
23
|
import { everyExpr, everyExprChild, everyStmtChild, everyStmtList } from "../../ir/traverse.js";
|
|
21
24
|
import { analyzeIntegerRanges, INT32_RANGE } from "../../ir/integer-ranges.js";
|
|
@@ -24,7 +27,7 @@ import { analyzeInt32Slots } from "../../ir/int32-slots.js";
|
|
|
24
27
|
import { analyzeFinalFields, constructorClass } from "../../ir/final-fields.js";
|
|
25
28
|
import { foldConstantGlobals } from "../../ir/constant-globals.js";
|
|
26
29
|
import { findIntegerViews } from "./integer-views.js";
|
|
27
|
-
import { findInt32Abis, INT32_ABI_SUFFIX } from "./int32-abi.js";
|
|
30
|
+
import { findInt32Abis, INT32_ABI_SUFFIX, SCALAR_UNION_DUMMY, SCALAR_UNION_RESULT, } from "./int32-abi.js";
|
|
28
31
|
import { findInt32Locals } from "./int32-locals.js";
|
|
29
32
|
import { exactInteger, narrowInteger } from "./integer-values.js";
|
|
30
33
|
import { findInitializerBindings, withInitializerBindings } from "../../ir/initializer-bindings.js";
|
|
@@ -35,9 +38,11 @@ import { computeMayThrow } from "../may-throw.js";
|
|
|
35
38
|
import { mangleArgPack, mangleAsyncAdoptCall, mangleAsyncAwaitCall, mangleAsyncSpawn, mangleBorrowedFunction, mangleClassObj, mangleClassStruct, mangleFnClosure, mangleFunction, mangleGenDrop, mangleGenSpawn, mangleGlobal, mangleLocal, mangleRecordStruct, mangleTrampoline, mangleWrapper, mangleBorrowingWrapper, mangleVtInstance, } from "../mangle.js";
|
|
36
39
|
import { analyzeCallLifetimes } from "./call-lifetimes.js";
|
|
37
40
|
import { canStackUnion, emitStackUnion, findLocalStackUnions } from "./stack-unions.js";
|
|
38
|
-
import {
|
|
41
|
+
import { emitStackObject, findLocalStackObjects, findReassignedStackObjects, stackObjectStruct, } from "./stack-objects.js";
|
|
42
|
+
import { allocateLocalUnion, emitScalarOptional, findLocalUnionStorage, isScalarOptionalSource, storeLocalUnion, } from "./local-union-storage.js";
|
|
39
43
|
import { BlockBuilder } from "./blocks.js";
|
|
40
44
|
import { NullableRefFields } from "./nullable-fields.js";
|
|
45
|
+
import { InlineUnionFields, loadInlineUnion, presentBits, stackUnionBox, storeInlineUnion, unionBoxBits, } from "./inline-unions.js";
|
|
41
46
|
import { emitLocalArrayRead, emitProjectedArrayRead, emitBorrowedArrayRead, findLocalArrayReads, findCallArrayReads, OptionalArrayReads, } from "./local-array-reads.js";
|
|
42
47
|
import { CheckedNarrows, emitCheckedNarrowReceiver } from "./checked-narrows.js";
|
|
43
48
|
import { emitDenseArrayGet, emitDenseArraySet } from "./dense-array-access.js";
|
|
@@ -50,7 +55,8 @@ import { ReferenceEffects } from "./reference-effects.js";
|
|
|
50
55
|
import { ReferenceWrites } from "./reference-writes.js";
|
|
51
56
|
import { LlvmDebugInfo } from "./debug-info.js";
|
|
52
57
|
import { StackCallbacks } from "./stack-callbacks.js";
|
|
53
|
-
import { findLoopArrayBorrows } from "./loop-array-borrows.js";
|
|
58
|
+
import { dynHoleRead, findLoopArrayBorrows } from "./loop-array-borrows.js";
|
|
59
|
+
import { findAppendedArrayLiterals } from "./appended-array-literals.js";
|
|
54
60
|
import { AmbientReceiverReaders, findConstantCallbacks } from "./constant-callbacks.js";
|
|
55
61
|
import { findScalarStringSlices, emitStringSliceSnapshot, } from "./string-slices.js";
|
|
56
62
|
import { LazyCaptures } from "./lazy-captures.js";
|
|
@@ -67,7 +73,7 @@ import { computeImmutableFields, stableGlobals } from "../immutability.js";
|
|
|
67
73
|
import { computePublishedTypes } from "../publication.js";
|
|
68
74
|
import { emitExpr } from "./expr-dispatch.js";
|
|
69
75
|
import { dynKind, raceAdapterFor, genResultThunkFor, childExitThunkFor, childExitSignalThunkFor, childDataThunkFor, execFileThunkFor, ipcMessageThunkFor, ipcSendThunkFor, emitterFixedAdapter, wrapEmitterListener, unwrapNullableClosure, closeBindThunkFor, closeOverrideWrapFor, } from "./expr-callbacks.js";
|
|
70
|
-
import { streamDataAdapter, streamDoneFnFor, cryptoBytesThunkFor, fsRenameThunkFor, streamCbThunkFor, zlibBytesThunkFor, } from "./expr-stream-callbacks.js";
|
|
76
|
+
import { streamDataAdapter, streamDoneFnFor, cryptoBytesThunkFor, cryptoIntThunkFor, fsRenameThunkFor, streamCbThunkFor, zlibBytesThunkFor, } from "./expr-stream-callbacks.js";
|
|
71
77
|
import { emitStableReceiver, resolveThunkFor, tagInSet, arrPush, emitArrayCopyLoop, emitStrIntrinsic, emitArrIntrinsic, emitDiscardedSplice, wrapNullable, emitMapNew, mapSet, emitMapLikeIntrinsic, emitSetNew, } from "./expr-containers.js";
|
|
72
78
|
import { emitIntegerLoopIndex, emitBytesIndex, emitBytesData, emitBytesLength, emitBytesGet, emitToUint32, emitBytesSet, emitBytesIntrinsic, } from "./expr-bytes.js";
|
|
73
79
|
import { emitRegexIntrinsic, emitRecordKeyGet, keyedRecordReadInto } from "./expr-records.js";
|
|
@@ -77,7 +83,8 @@ import { emitChildProcessLibCall, emitAsyncContextLibCall, emitProcessLibCall, e
|
|
|
77
83
|
import { emitStreamLibCall } from "./lib-stream.js";
|
|
78
84
|
import { emitNetworkHttpLibCall } from "./lib-network.js";
|
|
79
85
|
import { emitAssertInspectLibCall, emitIoLibCall, emitGenericLibCall, emitLibCall, } from "./lib-dispatch.js";
|
|
80
|
-
import { buildClassGraph, classMembershipIntervals, emitClassMembershipHelper, classEnvironmentIndex, classFieldIndex, classStructSym, } from "./classes.js";
|
|
86
|
+
import { buildClassGraph, classMembershipIntervals, emitClassMembershipHelper, classEnvironmentIndex, classFieldIndex, classStructSym, programLifetimeClass, } from "./classes.js";
|
|
87
|
+
import { LifetimeRegions, REGION_TYPES } from "./regions.js";
|
|
81
88
|
import { LlDyn } from "./dyn.js";
|
|
82
89
|
import { VirtualBorrows } from "./virtual-borrows.js";
|
|
83
90
|
import { LlvmUnsupportedError } from "./unsupported.js";
|
|
@@ -85,10 +92,10 @@ import { LlWalkers } from "./walkers.js";
|
|
|
85
92
|
import { isObjectArm, NULLABLE_ABSENT, NULLABLE_NULL, NullableUnions } from "./nullable-unions.js";
|
|
86
93
|
import { emitNullablePresent, emitUnionPeek, emitUnionTag } from "./union-repr.js";
|
|
87
94
|
import { literalCapWord, literalCapWord32 } from "./string-key-hash.js";
|
|
88
|
-
import { NUMBER_MAP_ENTRY_DECL, STRING_MAP_ENTRY_DECL } from "./map-number-lookup.js";
|
|
89
|
-
import { STRING_READ_HELPERS } from "./string-reads.js";
|
|
95
|
+
import { MAP_ITER_DECL, NUMBER_MAP_ENTRY_DECL, STRING_MAP_ENTRY_DECL, } from "./map-number-lookup.js";
|
|
96
|
+
import { STRING_READ_HELPERS, stringScanDecl } from "./string-reads.js";
|
|
90
97
|
import { emitConcatInputs, emitMixedConcat, numberPart, stringParts, } from "./string-construction.js";
|
|
91
|
-
import { arrNewCall, boxAccess, boxNewCall, boxReleaseSym, computeTraced, elemAccess, emitInlineRcHelpers, emitNullableRetainWrappers, FN_ATTRS, inlineRcDecls, llFieldType, releaseSym, retainSym, traceArg, typedRefConstructor, vAdapters, } from "./shapes.js";
|
|
98
|
+
import { arrNewCall, boxAccess, boxNewCall, boxReleaseSym, computeTraced, elemAccess, emitInlineRcHelpers, emitNullableRetainWrappers, FN_ATTRS, inlineRcDecls, limitInlineDynReleases, llFieldType, releaseSym, retainSym, traceArg, typedRefConstructor, vAdapters, } from "./shapes.js";
|
|
92
99
|
import { INLINE_LITERAL_BYTES, literalEqualityDefinition } from "./string-literal-equality.js";
|
|
93
100
|
export { LlvmUnsupportedError } from "./unsupported.js";
|
|
94
101
|
function ffiCallbackDummyLl(callback) {
|
|
@@ -122,14 +129,14 @@ export function emitLlvmModule(input, options = {}) {
|
|
|
122
129
|
const mod = unshareNodes(input);
|
|
123
130
|
// Keep source storage intact for debugger inspection in dev builds.
|
|
124
131
|
return new LlEmitter(options.debugSources === undefined
|
|
125
|
-
? scalarizeNumericRecords(specializeNumericCalls(foldConstantGlobals(mod), mangleFunction))
|
|
132
|
+
? addRecordResultEntries(scalarizeNumericRecords(specializeNumericCalls(foldConstantGlobals(mod), mangleFunction)))
|
|
126
133
|
: mod, options).emit();
|
|
127
134
|
}
|
|
128
135
|
/** Keep large translation units below the host's single-string limit. */
|
|
129
136
|
export function emitLlvmModuleSource(input, options = {}) {
|
|
130
137
|
const mod = unshareNodes(input);
|
|
131
138
|
const parts = new LlEmitter(options.debugSources === undefined
|
|
132
|
-
? scalarizeNumericRecords(specializeNumericCalls(foldConstantGlobals(mod), mangleFunction))
|
|
139
|
+
? addRecordResultEntries(scalarizeNumericRecords(specializeNumericCalls(foldConstantGlobals(mod), mangleFunction)))
|
|
133
140
|
: mod, options).emitParts();
|
|
134
141
|
const length = parts.reduce((total, part) => total + part.length, Math.max(0, parts.length - 1));
|
|
135
142
|
if (length <= 256 * 1024 * 1024)
|
|
@@ -137,7 +144,7 @@ export function emitLlvmModuleSource(input, options = {}) {
|
|
|
137
144
|
return parts.flatMap((part, index) => (index === 0 ? [part] : ["\n", part]));
|
|
138
145
|
}
|
|
139
146
|
function llStrBytes(text) {
|
|
140
|
-
return llBytes(
|
|
147
|
+
return llBytes(wtf8Bytes(text));
|
|
141
148
|
}
|
|
142
149
|
const NO_BORROWED = new Set();
|
|
143
150
|
/** Whether any node of `e` names the local (reads, writes, declarations,
|
|
@@ -181,6 +188,10 @@ export class LlEmitter {
|
|
|
181
188
|
scalarStringSlices = new Map();
|
|
182
189
|
stringSlices = new Map();
|
|
183
190
|
localStackUnions = new Map();
|
|
191
|
+
localStackObjects = new Map();
|
|
192
|
+
reassignedStackObjects = new Set();
|
|
193
|
+
/** The binding slot of each reassigned stack-object local. */
|
|
194
|
+
stackObjectSlots = new Map();
|
|
184
195
|
localUnionStorageProofs = new Map();
|
|
185
196
|
localUnionStorage = new Map();
|
|
186
197
|
integerArrayBindings = new Set();
|
|
@@ -203,6 +214,18 @@ export class LlEmitter {
|
|
|
203
214
|
}
|
|
204
215
|
this.fieldPointerTags.set(ptr, tag);
|
|
205
216
|
}
|
|
217
|
+
/** The alias tag of a runtime word that emitted code reads and writes
|
|
218
|
+
* outside every field (the lifetime-region count, owner and cursors). */
|
|
219
|
+
memoryAliasAttachment(category) {
|
|
220
|
+
if (this.debug !== null)
|
|
221
|
+
return "";
|
|
222
|
+
let tag = this.fieldAliasTags.get(category);
|
|
223
|
+
if (tag === undefined) {
|
|
224
|
+
tag = 2 + this.fieldAliasTags.size * 2;
|
|
225
|
+
this.fieldAliasTags.set(category, tag);
|
|
226
|
+
}
|
|
227
|
+
return `, !tbaa !${tag}`;
|
|
228
|
+
}
|
|
206
229
|
fieldAliasAttachment(ptr) {
|
|
207
230
|
const tag = this.fieldPointerTags.get(ptr);
|
|
208
231
|
return tag === undefined ? "" : `, !tbaa !${tag}`;
|
|
@@ -217,10 +240,12 @@ export class LlEmitter {
|
|
|
217
240
|
return lines;
|
|
218
241
|
}
|
|
219
242
|
debug;
|
|
243
|
+
/** Projection-only scalar objects may live in frame storage (stack-objects.ts). */
|
|
244
|
+
stackObjects;
|
|
220
245
|
debugScope = null;
|
|
221
246
|
sizeType;
|
|
222
247
|
ffiExtendNarrowIntegers;
|
|
223
|
-
|
|
248
|
+
cycleBufOffset;
|
|
224
249
|
/** Emitted ScrCycType descriptors so far (their collector statistics
|
|
225
250
|
* indices; see ShapeHost.nextCycKind). */
|
|
226
251
|
cycKinds = 0;
|
|
@@ -264,6 +289,8 @@ export class LlEmitter {
|
|
|
264
289
|
unitInstances = new Map();
|
|
265
290
|
/** unionId → symbol of the union's immortal ABSENT field-slot instance. */
|
|
266
291
|
absentInstances = new Map();
|
|
292
|
+
/** The zeroed box an inline store reads for a NULL union dummy. */
|
|
293
|
+
needsUnionNone = false;
|
|
267
294
|
/** unionId → symbol of a flag set once a checked-dynamic cast caches one
|
|
268
295
|
* of the union's boxes. A cached box is refreshed in place, possibly with
|
|
269
296
|
* a tag that another union numbers apart, so it is never shared. */
|
|
@@ -306,7 +333,11 @@ export class LlEmitter {
|
|
|
306
333
|
/** Inline RC fast-path helpers requested by call sites (shapes.ts); null
|
|
307
334
|
* when inline RC is off. */
|
|
308
335
|
rcHelpers;
|
|
336
|
+
rcMode;
|
|
337
|
+
rcHelpersNoinline;
|
|
309
338
|
fnByName = new Map();
|
|
339
|
+
/** Empty literals that construct with inline slots (appended-array-literals.ts). */
|
|
340
|
+
appendedArrayLiterals = new Set();
|
|
310
341
|
/** Emitted LLVM text of every IR function body, by function name: the
|
|
311
342
|
* fiberless-async analysis scans it for suspension entry points. */
|
|
312
343
|
fnDefText = new Map();
|
|
@@ -318,6 +349,8 @@ export class LlEmitter {
|
|
|
318
349
|
* whose bindings end with the list (emitBlock and function bodies). */
|
|
319
350
|
stmtCursor = null;
|
|
320
351
|
optionalArrayReads;
|
|
352
|
+
/** Union sources a binding or projection can hold in a stack box. */
|
|
353
|
+
unionSources;
|
|
321
354
|
checkedNarrows;
|
|
322
355
|
callArrayReads = new Map();
|
|
323
356
|
mapReadLifetimes = { locals: new Map(), arguments: new Map() };
|
|
@@ -413,6 +446,10 @@ export class LlEmitter {
|
|
|
413
446
|
* typeKey → thunk symbol. */
|
|
414
447
|
resolveThunks = new Map();
|
|
415
448
|
resolveThunkDefs = [];
|
|
449
|
+
/** Inline array searches used by the module (array-search.ts). */
|
|
450
|
+
arraySearchKinds = new Set();
|
|
451
|
+
/** Typed-ref recipe constants by type key (lazy receivers). */
|
|
452
|
+
typedRefRecipes = new Map();
|
|
416
453
|
/** ReadableStream.from adapters keep typed arrays by reference and box
|
|
417
454
|
* one current element per pull. */
|
|
418
455
|
streamFromArrayAdapters = new Map();
|
|
@@ -424,6 +461,7 @@ export class LlEmitter {
|
|
|
424
461
|
dynPromiseAdapters = new Map();
|
|
425
462
|
unionsById = new Map();
|
|
426
463
|
nullableFields;
|
|
464
|
+
inlineUnions;
|
|
427
465
|
/** Unions whose values are nullable arm pointers (nullable-unions.ts). */
|
|
428
466
|
nullableUnions;
|
|
429
467
|
/** The union table without nullable unions: the stack-box analyses. */
|
|
@@ -530,6 +568,9 @@ export class LlEmitter {
|
|
|
530
568
|
currentReturnType = VOID;
|
|
531
569
|
/** The current body returns its number result as i32. */
|
|
532
570
|
currentInt32Result = false;
|
|
571
|
+
/** The function's i32 entry returns its scalar union result as tag and
|
|
572
|
+
* payload bits (Int32Abi.union). */
|
|
573
|
+
currentUnionResult = false;
|
|
533
574
|
/** Active only while emitting a body lowered with LLVM's
|
|
534
575
|
* switched-coroutine intrinsics (wasm32 async bodies and generators,
|
|
535
576
|
* native synchronous generators; see coroLowered). */
|
|
@@ -538,6 +579,8 @@ export class LlEmitter {
|
|
|
538
579
|
* generator bodies): yieldExpr emission reads them, and emitTryCatch's
|
|
539
580
|
* catch prologue emits the GENRET sentinel re-unwind exactly here. */
|
|
540
581
|
currentGenerator = null;
|
|
582
|
+
/** The function being emitted is an async generator body. */
|
|
583
|
+
currentAsyncGenerator = false;
|
|
541
584
|
/** Active optional-chain bind slots, by chain id (chainRecv reads). */
|
|
542
585
|
chainSlots = new Map();
|
|
543
586
|
logArgSlots = 0;
|
|
@@ -565,6 +608,7 @@ export class LlEmitter {
|
|
|
565
608
|
options.wasi === true || ffiExtendsNarrowIntegers(options.targetTriple);
|
|
566
609
|
this.wasi = options.wasi === true;
|
|
567
610
|
this.stacklessGenerators = !this.wasi && mod.workers !== true && this.debug === null;
|
|
611
|
+
this.stackObjects = this.debug === null;
|
|
568
612
|
// An empty triple targets the host, as for executableTls below: the
|
|
569
613
|
// Node-hosted CLI passes none, the native CLI passes its toolchain's, and
|
|
570
614
|
// both must emit the same module for the same target.
|
|
@@ -590,16 +634,17 @@ export class LlEmitter {
|
|
|
590
634
|
this.emitLibraryIdentity = options.emitLibraryIdentity !== false;
|
|
591
635
|
this.runtimeAbiMarker = options.runtimeAbiMarker === true;
|
|
592
636
|
this.detachedExit = options.detachedExit === true;
|
|
593
|
-
this.rcHelpers = options.inlineRc
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
//
|
|
597
|
-
this.
|
|
637
|
+
this.rcHelpers = options.inlineRc !== undefined ? new Set() : null;
|
|
638
|
+
this.rcMode = options.inlineRc;
|
|
639
|
+
this.rcHelpersNoinline = options.rcHelpersNoinline === true;
|
|
640
|
+
// ScrCycHdr.buf sits 4 bytes behind every object on every target.
|
|
641
|
+
this.cycleBufOffset = CYC_HDR - CYC_BUF;
|
|
598
642
|
this.ffiCallbackAdapters = allocateFfiCallbackAdapters(mod.ffiImports ?? []);
|
|
599
643
|
this.ffiHasRetainedCallback = hasRetainedFfiCallback(mod.ffiImports ?? []);
|
|
600
644
|
this.ffiHasForeignCallback = hasForeignFfiCallback(mod.ffiImports ?? []);
|
|
601
645
|
for (const fn of mod.functions)
|
|
602
646
|
this.fnByName.set(fn.name, fn);
|
|
647
|
+
this.appendedArrayLiterals = findAppendedArrayLiterals(mod);
|
|
603
648
|
for (const entry of mod.ffiImports ?? []) {
|
|
604
649
|
this.ffiByName.set(entry.name, entry);
|
|
605
650
|
}
|
|
@@ -629,10 +674,21 @@ export class LlEmitter {
|
|
|
629
674
|
this.immortalValues.add("null");
|
|
630
675
|
this.immortalValues.add(NULLABLE_NULL);
|
|
631
676
|
this.nullableFields = new NullableRefFields(mod.classes ?? [], this.boxedUnionsById);
|
|
677
|
+
this.inlineUnions = new InlineUnionFields(this.boxedUnionsById, mod.classes ?? []);
|
|
678
|
+
for (const r of mod.records ?? [])
|
|
679
|
+
this.recordsById.set(r.id, r);
|
|
632
680
|
// Optional array reads also cover nullable unions: emitLocalArrayRead
|
|
633
681
|
// then yields the (borrowed or owned) element pointer, not a stack box.
|
|
634
682
|
// Arrays of such a union are read the same way.
|
|
635
683
|
this.optionalArrayReads = new OptionalArrayReads(this.fnByName, this.unionsById, (id) => this.nullableUnions.has(id));
|
|
684
|
+
this.unionSources = {
|
|
685
|
+
unions: this.boxedUnionsById,
|
|
686
|
+
receiverUnions: this.unionsById,
|
|
687
|
+
nullableField: (e) => this.nullableFieldGet(e) !== null,
|
|
688
|
+
inlineField: (e) => this.inlineFieldGet(e),
|
|
689
|
+
arrayRead: (e) => this.optionalArrayReads.get(e) !== null,
|
|
690
|
+
scalarCall: (e) => this.scalarResultCall(e),
|
|
691
|
+
};
|
|
636
692
|
this.checkedNarrows = new CheckedNarrows(this.fnByName);
|
|
637
693
|
this.referenceEffects = new ReferenceEffects(this.fnByName, (call) => this.optionalArrayReads.get(call) !== null, mod.classes ?? []);
|
|
638
694
|
if (this.debug === null)
|
|
@@ -678,23 +734,26 @@ export class LlEmitter {
|
|
|
678
734
|
walkParameters.set(fn.name, indexes);
|
|
679
735
|
}
|
|
680
736
|
}
|
|
681
|
-
this.callLifetimes = analyzeCallLifetimes(this.fnByName, (className, field) => this.nullableFields.get(className, field) !== null, walkParameters)
|
|
737
|
+
this.callLifetimes = analyzeCallLifetimes(this.fnByName, (className, field) => this.nullableFields.get(className, field) !== null, walkParameters, new Set([...this.int32Abis].filter(([, abi]) => abi.union).map(([name]) => name)), {
|
|
738
|
+
record: (shapeId, field) => this.recordFieldInline(shapeId, field),
|
|
739
|
+
classField: (className, field) => this.inlineUnions.classField(className, field),
|
|
740
|
+
});
|
|
682
741
|
this.constantCallbacks = findConstantCallbacks(mod, this.callLifetimes);
|
|
683
742
|
this.stackCallbacks = new StackCallbacks(this.fnByName);
|
|
684
743
|
this.receiverReaders = new AmbientReceiverReaders(this.fnByName);
|
|
685
744
|
this.stackCaptures = new StackCaptures(this.fnByName, this.callLifetimes, this.stackCallbacks);
|
|
686
745
|
this.lazyCaptures = new LazyCaptures(this.fnByName);
|
|
687
|
-
for (const r of mod.records ?? [])
|
|
688
|
-
this.recordsById.set(r.id, r);
|
|
689
746
|
const traced = computeTraced(mod);
|
|
690
747
|
this.tracedShapes = traced.shapes;
|
|
691
748
|
this.tracedUnions = traced.unions;
|
|
692
749
|
this.shapeHost = {
|
|
693
750
|
sizeType: this.sizeType,
|
|
694
|
-
|
|
751
|
+
cycleBufOffset: this.cycleBufOffset,
|
|
695
752
|
tracedShapes: this.tracedShapes,
|
|
696
753
|
tracedUnions: this.tracedUnions,
|
|
697
754
|
nullableUnions: this.nullableUnions,
|
|
755
|
+
inlineUnions: this.inlineUnions,
|
|
756
|
+
unionNoneRef: () => this.unionNoneRef(),
|
|
698
757
|
recordsById: this.recordsById,
|
|
699
758
|
recordCloneShapes: this.recordCloneShapes,
|
|
700
759
|
objectAudit: options.objectAudit !== false,
|
|
@@ -708,6 +767,8 @@ export class LlEmitter {
|
|
|
708
767
|
// paths address its thread-local state.
|
|
709
768
|
threadLocalAlloc: mod.workers === true,
|
|
710
769
|
rcHelpers: this.rcHelpers,
|
|
770
|
+
...(this.rcMode !== undefined ? { rcMode: this.rcMode } : {}),
|
|
771
|
+
...(this.rcHelpersNoinline ? { rcHelpersNoinline: true } : {}),
|
|
711
772
|
nextCycKind: () => FIRST_EMITTED_CYC_KIND + this.cycKinds++,
|
|
712
773
|
unionsById: this.unionsById,
|
|
713
774
|
declare: (decl) => this.declare(decl),
|
|
@@ -723,6 +784,7 @@ export class LlEmitter {
|
|
|
723
784
|
liveDynUnionRefAdapter: (type) => this.liveDynUnionRefAdapter(type),
|
|
724
785
|
dynPromiseAdapter: (type) => this.dynPromiseAdapter(type),
|
|
725
786
|
isErrorClass: (name) => this.classMeta.get(name)?.root.def.name === "%Error",
|
|
787
|
+
classRootOf: (name) => this.classMeta.get(name)?.root.def.name,
|
|
726
788
|
classSubtypes: (name) => {
|
|
727
789
|
const target = this.classMetaOf(name);
|
|
728
790
|
const intervals = classMembershipIntervals(this.classMeta, target.def.name);
|
|
@@ -733,6 +795,7 @@ export class LlEmitter {
|
|
|
733
795
|
pendingTestLines: (dest) => this.pendingTestLines(dest),
|
|
734
796
|
virtualEntry: (implFn) => this.virtualEntry(implFn),
|
|
735
797
|
programLifetime: this.programLifetime,
|
|
798
|
+
regionAliasTag: (word) => this.memoryAliasAttachment(`region.${word}`),
|
|
736
799
|
};
|
|
737
800
|
this.walkers = new LlWalkers(this.shapeHost);
|
|
738
801
|
this.dyn = new LlDyn(this.shapeHost);
|
|
@@ -755,13 +818,16 @@ export class LlEmitter {
|
|
|
755
818
|
this.tdzGlobals.set(g.id, g.name);
|
|
756
819
|
}
|
|
757
820
|
this.stableGlobals = stableGlobals(mod);
|
|
758
|
-
// Runtime error, EventEmitter,
|
|
759
|
-
// Subclasses embed the
|
|
821
|
+
// Runtime error, EventEmitter, stream, EventTarget and Event classes
|
|
822
|
+
// have known layouts. Subclasses embed the runtime prefixes from
|
|
823
|
+
// classes.ts.
|
|
760
824
|
const classes = mod.classes ?? [];
|
|
761
825
|
for (const cls of classes) {
|
|
762
826
|
if (cls.runtime &&
|
|
763
827
|
!RUNTIME_ERROR_CLASSES.has(cls.name) &&
|
|
764
828
|
cls.name !== RUNTIME_EMITTER_CLASS &&
|
|
829
|
+
cls.name !== RUNTIME_EVENT_TARGET_CLASS &&
|
|
830
|
+
cls.name !== RUNTIME_EVENT_CLASS &&
|
|
765
831
|
!RUNTIME_STREAM_CLASSES.has(cls.name)) {
|
|
766
832
|
throw new LlvmUnsupportedError(`classDef:${cls.name}`, cls.loc);
|
|
767
833
|
}
|
|
@@ -770,6 +836,17 @@ export class LlEmitter {
|
|
|
770
836
|
// whole-program preorder numbering for instanceof over runtime and
|
|
771
837
|
// compiled error objects, and the per-hierarchy virtual slot lists.
|
|
772
838
|
this.classMeta = buildClassGraph(mod, this.fnByName);
|
|
839
|
+
if (mod.lifetimeRegions === true) {
|
|
840
|
+
this.regions = new LifetimeRegions(this.shapeHost, mod, this.classMeta, (meta) => programLifetimeClass(this.shapeHost, meta), this.nullableFields);
|
|
841
|
+
const regions = this.regions;
|
|
842
|
+
// Member names differ from LifetimeRegions' own, which keeps the
|
|
843
|
+
// record from reading as that class's protocol.
|
|
844
|
+
this.shapeHost.regions = {
|
|
845
|
+
rcBody: (fnName, ret, comment) => regions.countBody(fnName, ret, comment),
|
|
846
|
+
newAlloc: (className, sizeOf) => regions.allocLines(className, sizeOf),
|
|
847
|
+
classDefinitions: (cls, sizeOf) => regions.classDefs(cls, sizeOf),
|
|
848
|
+
};
|
|
849
|
+
}
|
|
773
850
|
for (const [name, rec] of RUNTIME_ERROR_CLASSES) {
|
|
774
851
|
const meta = this.classMeta.get(name);
|
|
775
852
|
if (!meta)
|
|
@@ -1110,7 +1187,7 @@ export class LlEmitter {
|
|
|
1110
1187
|
return this.emitParts().join("\n");
|
|
1111
1188
|
}
|
|
1112
1189
|
emitParts() {
|
|
1113
|
-
const parts = this.emitModuleParts();
|
|
1190
|
+
const parts = limitInlineDynReleases(this.emitModuleParts());
|
|
1114
1191
|
if (!this.executableTls)
|
|
1115
1192
|
return parts;
|
|
1116
1193
|
// A worker executable's thread-locals all live in the executable's own
|
|
@@ -1163,7 +1240,7 @@ export class LlEmitter {
|
|
|
1163
1240
|
// Module globals, FIRST OCCURRENCE per id: a class-expression static
|
|
1164
1241
|
// instantiated through several mixin applications registers one global
|
|
1165
1242
|
// id several times (2041-mixin-values) — C's tentative definitions
|
|
1166
|
-
//
|
|
1243
|
+
// accept the duplicates without an error, LLVM rejects redefinition, so the
|
|
1167
1244
|
// storage AND the release emit once per id here.
|
|
1168
1245
|
const seenGlobalIds = new Set();
|
|
1169
1246
|
const globals = (this.mod.globals ?? []).filter((g) => {
|
|
@@ -1399,9 +1476,11 @@ export class LlEmitter {
|
|
|
1399
1476
|
// write/abort declarations).
|
|
1400
1477
|
const helpers = [
|
|
1401
1478
|
...this.helperDefs(),
|
|
1479
|
+
...emitArraySearchHelpers(this.arraySearchKinds, this.sizeType, (line) => this.declare(line)),
|
|
1402
1480
|
...emitClassMembershipHelper(this.classMeta, this.sizeType),
|
|
1403
1481
|
...(this.publishWalkersCache?.defs() ?? []),
|
|
1404
1482
|
...this.publishedClassNamesDefs(),
|
|
1483
|
+
...(this.regions?.moduleDefs() ?? []),
|
|
1405
1484
|
];
|
|
1406
1485
|
if (this.constantNumericTables.size > 0)
|
|
1407
1486
|
this.declare(`declare double @scr_arr_get_number(ptr, double)`);
|
|
@@ -1447,17 +1526,22 @@ export class LlEmitter {
|
|
|
1447
1526
|
? []
|
|
1448
1527
|
: [`%ScrMapRc = type { ${this.sizeType}, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr }`]),
|
|
1449
1528
|
// The complete ScrMap and its { key, val, hash } entry, read by the
|
|
1450
|
-
// inline number-key lookup (sc_map_entry_f64)
|
|
1451
|
-
//
|
|
1452
|
-
//
|
|
1453
|
-
|
|
1529
|
+
// inline number-key lookup (sc_map_entry_f64) and the inline
|
|
1530
|
+
// iteration steps (sc_map_iter_entry): field 9 is the entry count,
|
|
1531
|
+
// field 11 the i64 absent-key filter, entries is field 13, the direct
|
|
1532
|
+
// index and its length fields 19 and 20.
|
|
1533
|
+
...(this.decls.has(NUMBER_MAP_ENTRY_DECL) ||
|
|
1534
|
+
this.decls.has(STRING_MAP_ENTRY_DECL) ||
|
|
1535
|
+
this.decls.has(MAP_ITER_DECL)
|
|
1454
1536
|
? [
|
|
1455
1537
|
`%ScrMapIx = type { ${this.sizeType}, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr, ${this.sizeType}, ${this.sizeType}, i64, ${this.sizeType}, ptr, ${this.sizeType}, ptr, ${this.sizeType}, ptr, ptr, ptr, ${this.sizeType} }`,
|
|
1456
1538
|
]
|
|
1457
1539
|
: []),
|
|
1458
1540
|
// String-keyed reference reads load the value slot of the entry
|
|
1459
1541
|
// scr_map_entry_str returns (map-number-lookup.ts).
|
|
1460
|
-
...(this.decls.has(NUMBER_MAP_ENTRY_DECL) ||
|
|
1542
|
+
...(this.decls.has(NUMBER_MAP_ENTRY_DECL) ||
|
|
1543
|
+
this.decls.has(STRING_MAP_ENTRY_DECL) ||
|
|
1544
|
+
this.decls.has(MAP_ITER_DECL)
|
|
1461
1545
|
? [`%ScrMapEntry = type { i64, i64, i64 }`]
|
|
1462
1546
|
: []),
|
|
1463
1547
|
// The runtime error prefix { rc, vt, name, message, code, cause } and the
|
|
@@ -1471,6 +1555,13 @@ export class LlEmitter {
|
|
|
1471
1555
|
// The runtime stream layout { rc, vt, reg, cls, st } — one struct
|
|
1472
1556
|
// for all five stream classes; stream subclasses embed it.
|
|
1473
1557
|
`%ScrStream = type { ${this.sizeType}, ptr, ptr, ptr, ptr }`,
|
|
1558
|
+
// The EventTarget and Event subclass prefixes { rc, vt, state, cls }.
|
|
1559
|
+
...(this.classMeta.has(RUNTIME_EVENT_TARGET_CLASS)
|
|
1560
|
+
? [`%ScrEventTargetObj = type { ${this.sizeType}, ptr, ptr, ptr }`]
|
|
1561
|
+
: []),
|
|
1562
|
+
...(this.classMeta.has(RUNTIME_EVENT_CLASS)
|
|
1563
|
+
? [`%ScrEventObj = type { ${this.sizeType}, ptr, ptr, ptr }`]
|
|
1564
|
+
: []),
|
|
1474
1565
|
// The catch-binding snapshot box { rc, kind, f64, b, payload,
|
|
1475
1566
|
// retain_fn, release_fn, trace_fn } — caughtTest kind reads and
|
|
1476
1567
|
// caughtNarrow payload extraction GEP through it (offsets match
|
|
@@ -1529,8 +1620,8 @@ export class LlEmitter {
|
|
|
1529
1620
|
// half carries the precomputed Map key hash (SCR_STR_HASH_CACHE).
|
|
1530
1621
|
// Bit 31 marks all-ASCII literals (SCR_STR_ASCII_BIT) on every target.
|
|
1531
1622
|
const capWord = this.sizeType === "i64"
|
|
1532
|
-
? literalCapWord(
|
|
1533
|
-
: literalCapWord32(
|
|
1623
|
+
? literalCapWord(wtf8Bytes(text))
|
|
1624
|
+
: literalCapWord32(wtf8Bytes(text));
|
|
1534
1625
|
out.push(`@${lit.sym} = internal global { ${this.sizeType}, ${this.sizeType}, ${this.sizeType}, [${lit.len + 1} x i8] } ` +
|
|
1535
1626
|
`{ ${this.sizeType} -1, ${this.sizeType} ${lit.len}, ${this.sizeType} ${capWord}, [${lit.len + 1} x i8] c"${llStrBytes(text)}" }`);
|
|
1536
1627
|
}
|
|
@@ -1583,6 +1674,8 @@ export class LlEmitter {
|
|
|
1583
1674
|
}
|
|
1584
1675
|
if (this.absentInstances.size > 0)
|
|
1585
1676
|
out.push(``);
|
|
1677
|
+
if (this.needsUnionNone)
|
|
1678
|
+
out.push(`@sc_union_none = internal constant %ScrUnion zeroinitializer ; NULL union dummy read by inline stores`, ``);
|
|
1586
1679
|
if (this.nullableUnions.usesNullSentinel) {
|
|
1587
1680
|
// `null` in every `C | null | undefined` union (NULL is undefined):
|
|
1588
1681
|
// one module-scope immortal object like the ABSENT sentinel.
|
|
@@ -1693,6 +1786,12 @@ export class LlEmitter {
|
|
|
1693
1786
|
}
|
|
1694
1787
|
if (this.streamIntervals.length > 0)
|
|
1695
1788
|
out.push(``);
|
|
1789
|
+
if ([...this.literals.keys(), ...this.cstrs.keys()].some(hasLoneSurrogate)) {
|
|
1790
|
+
// The runtime skips surrogate work until a lone surrogate may exist
|
|
1791
|
+
// (scr_wtf8_any); its own producers note one, and literals do here.
|
|
1792
|
+
out.push(`declare void @scr_wtf8_note()`, ``);
|
|
1793
|
+
stamps.push(` call void @scr_wtf8_note()`);
|
|
1794
|
+
}
|
|
1696
1795
|
if (this.errorIntervals.length > 0 && this.tracedShapes.has("object:%Error")) {
|
|
1697
1796
|
// The cycle fixpoint marked the Error hierarchy (a user subclass
|
|
1698
1797
|
// holds cycle-capable fields — capability is hierarchy-uniform), so
|
|
@@ -1991,7 +2090,7 @@ export class LlEmitter {
|
|
|
1991
2090
|
case "i64":
|
|
1992
2091
|
// Inbound declared-integer edge (ask 4): the helper converts
|
|
1993
2092
|
// exactly or delivers the host-contract trap (past ±(2^53−1)
|
|
1994
|
-
// the value cannot ride f64 without
|
|
2093
|
+
// the value cannot ride f64 without rounding).
|
|
1995
2094
|
params.push(`i64 %a${i}`);
|
|
1996
2095
|
body.push(` %c${i} = call double @scr_library_i64_in(i64 %a${i}, ptr @sc_lib_int_trap_${e.symbol})`);
|
|
1997
2096
|
args.push(`double %c${i}`);
|
|
@@ -2099,6 +2198,15 @@ export class LlEmitter {
|
|
|
2099
2198
|
? ` %i = add i64 ${mapIndex.wide}, 0`
|
|
2100
2199
|
: ` %i = trunc i64 ${mapIndex.wide} to ${sz}`, ` %dp = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 19`, ` %dense = load ptr, ptr %dp`, ` %sp = getelementptr inbounds i32, ptr %dense, ${sz} %i`, ` %s = load i32, ptr %sp`, ` %empty = icmp eq i32 %s, 0`, ` br i1 %empty, label %miss, label %hit`, `hit:`, ` %e32 = sub i32 %s, 1`, sz === "i32" ? ` %e = add i32 %e32, 0` : ` %e = zext i32 %e32 to ${sz}`, ` %ep = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 13`, ` %entries = load ptr, ptr %ep`, ` %found = getelementptr inbounds %ScrMapEntry, ptr %entries, ${sz} %e`, ` ret ptr %found`, `miss:`, ` ret ptr null`, `outside:`, ` %dense.any = icmp ne ${sz} %nd, 0`, ` br i1 %dense.any, label %miss, label %slow`, `slow:`, ` %r = call ptr @scr_map_entry_f64(ptr %m, double %k)`, ` ret ptr %r`, `}`, ``);
|
|
2101
2200
|
}
|
|
2201
|
+
// Map/Set iteration steps read the entries array inline: an index is
|
|
2202
|
+
// live when it is below the entry count and its entry's cached hash is
|
|
2203
|
+
// nonzero (a tombstone's is zero), as scr_map_iter_live decides. The
|
|
2204
|
+
// entry count is read again at every step, so entries appended during
|
|
2205
|
+
// the iteration are visited.
|
|
2206
|
+
if (this.decls.has(MAP_ITER_DECL)) {
|
|
2207
|
+
const sz = this.sizeType;
|
|
2208
|
+
defs.push(`define internal ptr @sc_map_iter_entry(ptr %m, double %i) ${FN_ATTRS} {`, `entry:`, ` %np = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 9`, ` %n = load ${sz}, ptr %np`, ` %nf = uitofp ${sz} %n to double`, ` %lo = fcmp oge double %i, 0.0`, ` %hi = fcmp olt double %i, %nf`, ` %in = and i1 %lo, %hi`, ` br i1 %in, label %load, label %none`, `load:`, ` %ix = fptoui double %i to ${sz}`, ` %ep = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 13`, ` %entries = load ptr, ptr %ep`, ` %e = getelementptr inbounds %ScrMapEntry, ptr %entries, ${sz} %ix`, ` %hp = getelementptr inbounds %ScrMapEntry, ptr %e, i32 0, i32 2`, ` %h = load i64, ptr %hp`, ` %live = icmp ne i64 %h, 0`, ` br i1 %live, label %yes, label %none`, `yes:`, ` ret ptr %e`, `none:`, ` ret ptr null`, `}`, ``, `define internal double @sc_map_iter_count(ptr %m) ${FN_ATTRS} {`, `entry:`, ` %np = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 9`, ` %n = load ${sz}, ptr %np`, ` %nf = uitofp ${sz} %n to double`, ` ret double %nf`, `}`, ``);
|
|
2209
|
+
}
|
|
2102
2210
|
// String-key Map/Set lookups test the map's absent-key filter inline
|
|
2103
2211
|
// (scr_map.c scr_map_filter_bits): a key whose two filter bits are not
|
|
2104
2212
|
// both set is absent, so most misses on small and medium maps return
|
|
@@ -2140,16 +2248,24 @@ export class LlEmitter {
|
|
|
2140
2248
|
defs.push(`define internal zeroext i1 @sc_str_eq(ptr %a, ptr %b) ${FN_ATTRS} {`, `entry:`, ` %same = icmp eq ptr %a, %b`, ` br i1 %same, label %yes, label %lengths`, `lengths:`, ` %alen.p = getelementptr inbounds %ScrStr, ptr %a, i32 0, i32 1`, ` %blen.p = getelementptr inbounds %ScrStr, ptr %b, i32 0, i32 1`, ` %alen = load ${this.sizeType}, ptr %alen.p`, ` %blen = load ${this.sizeType}, ptr %blen.p`, ` %samelen = icmp eq ${this.sizeType} %alen, %blen`, ` br i1 %samelen, label %bytes, label %no`, `bytes:`, ` %eq = call zeroext i1 @scr_str_eq(ptr %a, ptr %b)`, ` ret i1 %eq`, `yes:`, ` ret i1 true`, `no:`, ` ret i1 false`, `}`, ``);
|
|
2141
2249
|
}
|
|
2142
2250
|
for (const [text, name] of this.literalEqualities) {
|
|
2143
|
-
defs.push(...literalEqualityDefinition(name,
|
|
2251
|
+
defs.push(...literalEqualityDefinition(name, wtf8Bytes(text), this.internLiteral(text), this.sizeType, FN_ATTRS), ``);
|
|
2144
2252
|
}
|
|
2145
2253
|
// String length and charCodeAt read proven-ASCII strings inline: bit 31
|
|
2146
2254
|
// of the capacity word (SCR_STR_ASCII_BIT, the low half's sign bit on
|
|
2147
2255
|
// little-endian targets) makes UTF-16 units bytes. Unproven strings and
|
|
2148
2256
|
// anything but an in-range index take the runtime's UTF-16 mapping.
|
|
2257
|
+
// A scan's receiver reads inline too where runtime state is ordinary
|
|
2258
|
+
// global storage (ScrStrScan; SCR_TL makes it thread-local otherwise).
|
|
2259
|
+
const scanInline = this.mod.workers !== true && this.mod.lib?.threadInstances !== true;
|
|
2260
|
+
let scanDeclared = false;
|
|
2149
2261
|
for (const helper of STRING_READ_HELPERS) {
|
|
2150
2262
|
if (!this.decls.has(helper.decl))
|
|
2151
2263
|
continue;
|
|
2152
|
-
|
|
2264
|
+
if (scanInline && !scanDeclared) {
|
|
2265
|
+
defs.push(stringScanDecl(this.sizeType), ``);
|
|
2266
|
+
scanDeclared = true;
|
|
2267
|
+
}
|
|
2268
|
+
defs.push(...helper.define(this.sizeType, FN_ATTRS, scanInline), ``);
|
|
2153
2269
|
}
|
|
2154
2270
|
// Ordering also decides inline when the first bytes differ: byte order
|
|
2155
2271
|
// is the plain comparison's order, and the UTF-16 order whenever both
|
|
@@ -2331,7 +2447,7 @@ export class LlEmitter {
|
|
|
2331
2447
|
* programs keep fibers too: their fiber epilogue owns context
|
|
2332
2448
|
* termination (a stopping worker rejects and observes the promise), which
|
|
2333
2449
|
* the fiberless wrapper does not reproduce. A missed suspension still
|
|
2334
|
-
* cannot reorder
|
|
2450
|
+
* cannot reorder execution undetected: the runtime traps when a context parks while a
|
|
2335
2451
|
* fiberless body is on its stack. */
|
|
2336
2452
|
fiberlessAsyncFunctions() {
|
|
2337
2453
|
const eligible = new Set();
|
|
@@ -2983,8 +3099,13 @@ export class LlEmitter {
|
|
|
2983
3099
|
* holding the ABSENT state surfaces as the ordinary undefined arm, so
|
|
2984
3100
|
* absence never travels beyond its slot (a later `{ f: r.f }` is an
|
|
2985
3101
|
* explicit, present property). */
|
|
2986
|
-
loadRecordField(ptr, t) {
|
|
2987
|
-
|
|
3102
|
+
loadRecordField(ptr, t, inline) {
|
|
3103
|
+
if (inline) {
|
|
3104
|
+
const { tag, bits } = loadInlineUnion(this.B, ptr);
|
|
3105
|
+
const present = presentBits(this.B, tag, bits, undefinedArmTag(t, this.unionsById));
|
|
3106
|
+
return stackUnionBox(this.B, this.sizeType, tag, present);
|
|
3107
|
+
}
|
|
3108
|
+
const v = this.loadField(ptr, t, false);
|
|
2988
3109
|
if (t.kind !== "union" || undefinedArmTag(t, this.unionsById) < 0)
|
|
2989
3110
|
return v;
|
|
2990
3111
|
const absent = this.fieldAbsentTest(v, t.unionId);
|
|
@@ -3197,11 +3318,13 @@ export class LlEmitter {
|
|
|
3197
3318
|
? "ret void"
|
|
3198
3319
|
: this.currentInt32Result
|
|
3199
3320
|
? "ret i32 0"
|
|
3200
|
-
:
|
|
3201
|
-
? `ret
|
|
3202
|
-
: t === "
|
|
3203
|
-
?
|
|
3204
|
-
:
|
|
3321
|
+
: this.currentUnionResult
|
|
3322
|
+
? `ret ${SCALAR_UNION_DUMMY}`
|
|
3323
|
+
: t === "double"
|
|
3324
|
+
? `ret double ${f64Lit(0)}`
|
|
3325
|
+
: t === "i1"
|
|
3326
|
+
? "ret i1 false"
|
|
3327
|
+
: "ret ptr null";
|
|
3205
3328
|
}
|
|
3206
3329
|
// Copy the entries now: later declarations extend these lexical scopes.
|
|
3207
3330
|
// Release order and the handler are part of the shared block's identity.
|
|
@@ -3644,6 +3767,7 @@ export class LlEmitter {
|
|
|
3644
3767
|
case "searchParams":
|
|
3645
3768
|
case "stats":
|
|
3646
3769
|
case "fileHandle":
|
|
3770
|
+
case "dir":
|
|
3647
3771
|
case "spawnRes":
|
|
3648
3772
|
case "child":
|
|
3649
3773
|
case "childStream":
|
|
@@ -3686,7 +3810,7 @@ export class LlEmitter {
|
|
|
3686
3810
|
}
|
|
3687
3811
|
/** Guard for helpers that build or read a union's `%ScrUnion` box
|
|
3688
3812
|
* directly (library-shaped unions with fixed arms): a nullable union
|
|
3689
|
-
* reaching one is an emitter bug
|
|
3813
|
+
* reaching one is an emitter bug and throws InternalCompilerError. */
|
|
3690
3814
|
requireBoxedUnion(unionId) {
|
|
3691
3815
|
if (this.nullableUnions.has(unionId))
|
|
3692
3816
|
throw new InternalCompilerError(`llvm emitter bug: nullable union ${unionId} reached a tagged-box helper`);
|
|
@@ -3819,7 +3943,7 @@ export class LlEmitter {
|
|
|
3819
3943
|
const p = this.B.tmp();
|
|
3820
3944
|
this.B.line(`${p} = getelementptr inbounds %${classStructSym(className)}, ptr ${objName}, i64 0, i32 ${index}`);
|
|
3821
3945
|
this.markFieldPointer(p, field);
|
|
3822
|
-
return { ptr: p, type };
|
|
3946
|
+
return { ptr: p, type, inline: this.inlineUnions.classField(className, field) };
|
|
3823
3947
|
}
|
|
3824
3948
|
/** `o->vt->pre` — the dynamic class's preorder number (borrowed object;
|
|
3825
3949
|
* the static class names which struct spelling carries the vt word). */
|
|
@@ -3870,8 +3994,10 @@ export class LlEmitter {
|
|
|
3870
3994
|
if (index < 0)
|
|
3871
3995
|
throw new InternalCompilerError(`llvm emitter bug: missing union field ${field}`);
|
|
3872
3996
|
layout = "record:";
|
|
3873
|
-
for (let i = 0; i <= index; i++)
|
|
3874
|
-
|
|
3997
|
+
for (let i = 0; i <= index; i++) {
|
|
3998
|
+
const type = shape.fields[i].type;
|
|
3999
|
+
layout += `${llFieldType(type, this.inlineUnions.record(type))};`;
|
|
4000
|
+
}
|
|
3875
4001
|
}
|
|
3876
4002
|
const group = groups.get(layout);
|
|
3877
4003
|
if (group)
|
|
@@ -3883,7 +4009,13 @@ export class LlEmitter {
|
|
|
3883
4009
|
this.unionFieldReadGroups.set(key, result);
|
|
3884
4010
|
return result;
|
|
3885
4011
|
}
|
|
3886
|
-
/** The
|
|
4012
|
+
/** The zeroed `%ScrUnion` constant (inline-unions.ts unionBoxBits). */
|
|
4013
|
+
unionNoneRef() {
|
|
4014
|
+
this.needsUnionNone = true;
|
|
4015
|
+
return "@sc_union_none";
|
|
4016
|
+
}
|
|
4017
|
+
/** The field-slot pointer of a record member (rc header at index 0).
|
|
4018
|
+
* `inline`: the slot stores a scalar union's tag and bits. */
|
|
3887
4019
|
recordFieldPtr(objName, shapeId, field) {
|
|
3888
4020
|
const shape = this.recordShape(shapeId);
|
|
3889
4021
|
const idx = shape.fields.findIndex((f) => f.name === field);
|
|
@@ -3891,7 +4023,8 @@ export class LlEmitter {
|
|
|
3891
4023
|
throw new InternalCompilerError(`llvm emitter bug: unknown field ${field} on shape ${shapeId}`);
|
|
3892
4024
|
const p = this.B.tmp();
|
|
3893
4025
|
this.B.line(`${p} = getelementptr inbounds %${mangleRecordStruct(shapeId)}, ptr ${objName}, i64 0, i32 ${idx + 1}`);
|
|
3894
|
-
|
|
4026
|
+
const type = shape.fields[idx].type;
|
|
4027
|
+
return { ptr: p, type, inline: this.inlineUnions.record(type) };
|
|
3895
4028
|
}
|
|
3896
4029
|
/** The overflow map's slot pointer on an index-signature shape. */
|
|
3897
4030
|
recordOvfPtr(objName, shapeId) {
|
|
@@ -3904,10 +4037,16 @@ export class LlEmitter {
|
|
|
3904
4037
|
this.B.line(`${v} = load ptr, ptr ${p}`);
|
|
3905
4038
|
return v;
|
|
3906
4039
|
}
|
|
3907
|
-
/** Loads a record field (i8-stored bools trunc to i1).
|
|
3908
|
-
|
|
4040
|
+
/** Loads a record field (i8-stored bools trunc to i1). An inline union
|
|
4041
|
+
* field answers a private stack box with the slot's own bits, ABSENT
|
|
4042
|
+
* included: it may only be borrowed. */
|
|
4043
|
+
loadField(ptr, t, inline) {
|
|
3909
4044
|
const B = this.B;
|
|
3910
|
-
|
|
4045
|
+
if (inline) {
|
|
4046
|
+
const { tag, bits } = loadInlineUnion(B, ptr);
|
|
4047
|
+
return stackUnionBox(B, this.sizeType, tag, bits);
|
|
4048
|
+
}
|
|
4049
|
+
const fieldTy = llFieldType(t, false);
|
|
3911
4050
|
const raw = B.tmp();
|
|
3912
4051
|
B.line(`${raw} = load ${fieldTy}, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
3913
4052
|
if (fieldTy !== "i8")
|
|
@@ -3916,10 +4055,46 @@ export class LlEmitter {
|
|
|
3916
4055
|
B.line(`${b} = trunc i8 ${raw} to i1`);
|
|
3917
4056
|
return b;
|
|
3918
4057
|
}
|
|
3919
|
-
/**
|
|
3920
|
-
|
|
4058
|
+
/** A record field of this shape stores its scalar union inline. */
|
|
4059
|
+
recordFieldInline(shapeId, field) {
|
|
4060
|
+
const type = this.recordShape(shapeId).fields.find((f) => f.name === field)?.type;
|
|
4061
|
+
return type !== undefined && this.inlineUnions.record(type);
|
|
4062
|
+
}
|
|
4063
|
+
/** The value a field store writes: an inline union slot copies the tag
|
|
4064
|
+
* and bits of a borrowed projection, so no box is built for it. */
|
|
4065
|
+
emitFieldValue(value, inline) {
|
|
4066
|
+
return inline ? this.emitUnionProjection(value) : this.emitExpr(value);
|
|
4067
|
+
}
|
|
4068
|
+
/** Overwrites a field with `v` (from emitFieldValue). A reference moves
|
|
4069
|
+
* in, and the old value is released AFTER the field is overwritten. */
|
|
4070
|
+
replaceField(ptr, type, inline, v) {
|
|
4071
|
+
if (!inline && isRefCounted(type)) {
|
|
4072
|
+
this.moveTemp(v);
|
|
4073
|
+
const old = this.B.tmp();
|
|
4074
|
+
this.B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
4075
|
+
this.storeField(ptr, type, v.name, false);
|
|
4076
|
+
this.releaseValue(old, type);
|
|
4077
|
+
return;
|
|
4078
|
+
}
|
|
4079
|
+
this.storeField(ptr, type, v.name, inline);
|
|
4080
|
+
}
|
|
4081
|
+
/** Stores `v` (from emitFieldValue) into a fresh field slot. */
|
|
4082
|
+
initField(ptr, type, inline, v) {
|
|
4083
|
+
if (!inline && isRefCounted(type))
|
|
4084
|
+
this.moveTemp(v);
|
|
4085
|
+
this.storeField(ptr, type, v.name, inline);
|
|
4086
|
+
}
|
|
4087
|
+
/** Stores a record field (i1 zext to the i8 storage). An inline union
|
|
4088
|
+
* field copies the tag and bits of the union value, which its owner
|
|
4089
|
+
* keeps. */
|
|
4090
|
+
storeField(ptr, t, value, inline) {
|
|
3921
4091
|
const B = this.B;
|
|
3922
|
-
|
|
4092
|
+
if (inline) {
|
|
4093
|
+
const { tag, bits } = unionBoxBits(B, value, this.unionNoneRef());
|
|
4094
|
+
storeInlineUnion(B, ptr, tag, bits);
|
|
4095
|
+
return;
|
|
4096
|
+
}
|
|
4097
|
+
const fieldTy = llFieldType(t, false);
|
|
3923
4098
|
if (fieldTy !== "i8") {
|
|
3924
4099
|
B.line(`store ${fieldTy} ${value}, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
3925
4100
|
return;
|
|
@@ -4389,7 +4564,7 @@ export class LlEmitter {
|
|
|
4389
4564
|
this.integerArrayBindings.clear();
|
|
4390
4565
|
this.loopArrayBorrows =
|
|
4391
4566
|
this.debug === null
|
|
4392
|
-
? findLoopArrayBorrows(fn, this.callLifetimes, this.referenceEffects, this.optionalArrayReads, this.referenceWrites)
|
|
4567
|
+
? findLoopArrayBorrows(fn, this.callLifetimes, this.referenceEffects, this.optionalArrayReads, this.referenceWrites, this.fnByName)
|
|
4393
4568
|
: new Set();
|
|
4394
4569
|
this.localArrayReads = findLocalArrayReads(fn, this.fnByName, this.unionsById, this.referenceEffects.functions, this.callLifetimes, this.optionalArrayReads, this.loopArrayBorrows, this.debug === null ? this.referenceEffects : undefined);
|
|
4395
4570
|
this.callArrayReads = findCallArrayReads(fn, this.optionalArrayReads, this.referenceEffects.functions, this.callLifetimes, this.debug === null ? this.referenceEffects : undefined);
|
|
@@ -4397,7 +4572,14 @@ export class LlEmitter {
|
|
|
4397
4572
|
this.debug === null ? findScalarStringSlices(fn, this.callLifetimes) : new Map();
|
|
4398
4573
|
this.mapReadLifetimes = findMapReadLifetimes(fn, this.boxedUnionsById, this.callLifetimes);
|
|
4399
4574
|
this.localStackUnions = findLocalStackUnions(fn, this.callLifetimes, this.boxedUnionsById);
|
|
4400
|
-
this.
|
|
4575
|
+
this.localStackObjects = this.stackObjects
|
|
4576
|
+
? findLocalStackObjects(this, fn, this.callLifetimes)
|
|
4577
|
+
: new Map();
|
|
4578
|
+
this.reassignedStackObjects = this.stackObjects
|
|
4579
|
+
? findReassignedStackObjects(this, fn, this.callLifetimes)
|
|
4580
|
+
: new Set();
|
|
4581
|
+
this.stackObjectSlots = new Map();
|
|
4582
|
+
this.localUnionStorageProofs = findLocalUnionStorage(fn, this.callLifetimes, this.unionSources);
|
|
4401
4583
|
this.localUnionStorage = new Map();
|
|
4402
4584
|
this.walkBorrows = this.walkBorrowsByFunction.get(fn.name) ?? new Set();
|
|
4403
4585
|
this.integerRanges = analyzeIntegerRanges(numericFn, this.int32Slots.facts(fn.name));
|
|
@@ -4417,7 +4599,9 @@ export class LlEmitter {
|
|
|
4417
4599
|
this.currentReturnType = fn.returnType;
|
|
4418
4600
|
const int32Abi = this.int32Abis.get(fn.name);
|
|
4419
4601
|
this.currentInt32Result = int32Abi?.result === true;
|
|
4602
|
+
this.currentUnionResult = int32Abi?.union === true;
|
|
4420
4603
|
this.currentGenerator = fn.generator ?? null;
|
|
4604
|
+
this.currentAsyncGenerator = fn.async === true && fn.generator !== undefined;
|
|
4421
4605
|
this.currentBorrowedReturn = this.borrowedReturns.has(fn.name);
|
|
4422
4606
|
this.inConstructor = this.constructorFunctions.has(fn.name);
|
|
4423
4607
|
this.currentCoro = null;
|
|
@@ -4604,6 +4788,9 @@ export class LlEmitter {
|
|
|
4604
4788
|
// whose unwind released everything down to depth 0).
|
|
4605
4789
|
if (fn.returnType.kind === "void" && !B.isTerminated()) {
|
|
4606
4790
|
this.releaseScope(this.scopes[0]);
|
|
4791
|
+
// Completing by falling off the end has nothing to await.
|
|
4792
|
+
if (this.currentAsyncGenerator)
|
|
4793
|
+
this.emitAsyncGenSettled();
|
|
4607
4794
|
if (this.currentCoro !== null) {
|
|
4608
4795
|
this.emitWasiFulfill(null);
|
|
4609
4796
|
B.terminate(`br label %${this.currentCoro.finalLabel}`);
|
|
@@ -4681,7 +4868,11 @@ export class LlEmitter {
|
|
|
4681
4868
|
// Lifted functions receive their closure first (the callValue ABI).
|
|
4682
4869
|
if (fn.captures !== undefined)
|
|
4683
4870
|
params.unshift("ptr %sc_env");
|
|
4684
|
-
const ret = int32Abi?.result
|
|
4871
|
+
const ret = int32Abi?.result
|
|
4872
|
+
? "i32"
|
|
4873
|
+
: int32Abi?.union
|
|
4874
|
+
? SCALAR_UNION_RESULT
|
|
4875
|
+
: this.llType(fn.returnType);
|
|
4685
4876
|
let attrs = coro !== null ? "#1" : FN_ATTRS;
|
|
4686
4877
|
// The shared indexed-read helper (lowerSafeIndexRead) is a dense bounds
|
|
4687
4878
|
// test, a state test and a load behind cold runtime fallbacks, called
|
|
@@ -4690,6 +4881,15 @@ export class LlEmitter {
|
|
|
4690
4881
|
// a call, and an integer index converts to a double and back across it.
|
|
4691
4882
|
if (fn.name.startsWith("%arr.idxOr."))
|
|
4692
4883
|
attrs = `inlinehint ${attrs}`;
|
|
4884
|
+
// Interface dispatch is a few key tests and direct calls ahead of the
|
|
4885
|
+
// checked dynamic call. Keeping that fallback out of line leaves the
|
|
4886
|
+
// tests small enough to inline at each call site.
|
|
4887
|
+
if (fn.name.startsWith("%dyn.class.protocol.fallback."))
|
|
4888
|
+
attrs = `noinline ${attrs}`;
|
|
4889
|
+
else if (fn.name.startsWith("%dyn.class.protocol."))
|
|
4890
|
+
attrs = `inlinehint ${attrs}`;
|
|
4891
|
+
if (fn.name.startsWith(RESULT_ENTRY_PREFIX))
|
|
4892
|
+
attrs = `inlinehint ${attrs}`;
|
|
4693
4893
|
const debug = this.debugScope === null ? "" : ` !dbg ${this.debugScope}`;
|
|
4694
4894
|
const symbol = borrowed ? mangleBorrowedFunction(fn.name) : mangleFunction(fn.name);
|
|
4695
4895
|
let body = `define internal ${ret} @${symbol}${int32Abi ? INT32_ABI_SUFFIX : ""}(${params.join(", ")}) ${attrs}${debug} { ; ${fn.name}\n${B.render()}\n}`;
|
|
@@ -4721,7 +4921,19 @@ export class LlEmitter {
|
|
|
4721
4921
|
args.push(`${type} %p${index}`);
|
|
4722
4922
|
});
|
|
4723
4923
|
const ret = this.llType(fn.returnType);
|
|
4724
|
-
const
|
|
4924
|
+
const entry = `@${symbol}${INT32_ABI_SUFFIX}(${args.join(", ")})`;
|
|
4925
|
+
if (abi.union) {
|
|
4926
|
+
// Box the register pair for every caller of the ordinary ABI.
|
|
4927
|
+
const B = new BlockBuilder();
|
|
4928
|
+
this.B = B;
|
|
4929
|
+
for (const line of lines)
|
|
4930
|
+
B.line(line.trim());
|
|
4931
|
+
const pair = B.tmp();
|
|
4932
|
+
B.line(`${pair} = call ${SCALAR_UNION_RESULT} ${entry}`);
|
|
4933
|
+
B.terminate(`ret ptr ${this.boxScalarUnion(pair, fn.returnType)}`);
|
|
4934
|
+
return `define internal ptr @${symbol}(${params.join(", ")}) ${FN_ATTRS} {\n${B.render()}\n}`;
|
|
4935
|
+
}
|
|
4936
|
+
const call = `call ${abi.result ? "i32" : ret} ${entry}`;
|
|
4725
4937
|
if (ret === "void")
|
|
4726
4938
|
lines.push(` ${call}`, " ret void");
|
|
4727
4939
|
else if (abi.result)
|
|
@@ -4730,6 +4942,85 @@ export class LlEmitter {
|
|
|
4730
4942
|
lines.push(` %r = ${call}`, ` ret ${ret} %r`);
|
|
4731
4943
|
return `define internal ${ret} @${symbol}(${params.join(", ")}) ${FN_ATTRS} {\nentry:\n${lines.join("\n")}\n}`;
|
|
4732
4944
|
}
|
|
4945
|
+
/** The SCALAR_UNION_RESULT pair of a `%ScrUnion` box of `type`. */
|
|
4946
|
+
scalarUnionPair(box, type) {
|
|
4947
|
+
const B = this.B;
|
|
4948
|
+
const unionId = type.kind === "union" ? type.unionId : "";
|
|
4949
|
+
const tag = this.unionTag(box, unionId);
|
|
4950
|
+
const payload = B.tmp(), bits = B.tmp(), partial = B.tmp(), pair = B.tmp();
|
|
4951
|
+
B.line(`${payload} = getelementptr inbounds %ScrUnion, ptr ${box}, i32 0, i32 5`);
|
|
4952
|
+
B.line(`${bits} = load i64, ptr ${payload}`);
|
|
4953
|
+
B.line(`${partial} = insertvalue ${SCALAR_UNION_RESULT} poison, i32 ${tag}, 0`);
|
|
4954
|
+
B.line(`${pair} = insertvalue ${SCALAR_UNION_RESULT} ${partial}, i64 ${bits}, 1`);
|
|
4955
|
+
return pair;
|
|
4956
|
+
}
|
|
4957
|
+
/** A private stack box holding a SCALAR_UNION_RESULT pair of `type`. */
|
|
4958
|
+
stackScalarUnion(pair, type) {
|
|
4959
|
+
const B = this.B;
|
|
4960
|
+
const box = B.slot(), tagSlot = B.slot(), payloadSlot = B.slot();
|
|
4961
|
+
B.entryAllocas.push(`${box} = alloca %ScrUnion`);
|
|
4962
|
+
B.entryAllocas.push(`${tagSlot} = getelementptr inbounds %ScrUnion, ptr ${box}, i32 0, i32 1`);
|
|
4963
|
+
B.entryAllocas.push(`${payloadSlot} = getelementptr inbounds %ScrUnion, ptr ${box}, i32 0, i32 5`);
|
|
4964
|
+
const tag = B.tmp(), bits = B.tmp();
|
|
4965
|
+
B.line(`${tag} = extractvalue ${SCALAR_UNION_RESULT} ${pair}, 0`);
|
|
4966
|
+
B.line(`${bits} = extractvalue ${SCALAR_UNION_RESULT} ${pair}, 1`);
|
|
4967
|
+
B.line(`store i32 ${tag}, ptr ${tagSlot}`);
|
|
4968
|
+
B.line(`store i64 ${bits}, ptr ${payloadSlot}`);
|
|
4969
|
+
return { name: box, type };
|
|
4970
|
+
}
|
|
4971
|
+
/** A direct call whose i32 entry returns its scalar union in registers. */
|
|
4972
|
+
scalarResultCall(e) {
|
|
4973
|
+
return e.kind === "call" && this.int32Abis.get(e.callee)?.union === true;
|
|
4974
|
+
}
|
|
4975
|
+
/** A fresh heap box (+1) for a SCALAR_UNION_RESULT pair of `type`; the
|
|
4976
|
+
* exception dummy (tag -1) answers NULL. */
|
|
4977
|
+
boxScalarUnion(pair, type) {
|
|
4978
|
+
const B = this.B;
|
|
4979
|
+
const tag = B.tmp(), bits = B.tmp();
|
|
4980
|
+
B.line(`${tag} = extractvalue ${SCALAR_UNION_RESULT} ${pair}, 0`);
|
|
4981
|
+
B.line(`${bits} = extractvalue ${SCALAR_UNION_RESULT} ${pair}, 1`);
|
|
4982
|
+
return this.boxScalarUnionBits(tag, bits, type);
|
|
4983
|
+
}
|
|
4984
|
+
/** A fresh heap box (+1) for an inline union field's value; the ABSENT
|
|
4985
|
+
* state reads as the undefined arm. */
|
|
4986
|
+
inlineFieldUnion(ptr, type) {
|
|
4987
|
+
const { tag, bits } = loadInlineUnion(this.B, ptr);
|
|
4988
|
+
return this.boxScalarUnionBits(tag, bits, type);
|
|
4989
|
+
}
|
|
4990
|
+
/** boxScalarUnion over a separate tag and payload bits. Unit arms answer
|
|
4991
|
+
* their immortal instances whatever the bits. */
|
|
4992
|
+
boxScalarUnionBits(tag, bits, type) {
|
|
4993
|
+
const B = this.B;
|
|
4994
|
+
const unionId = type.kind === "union" ? type.unionId : "";
|
|
4995
|
+
const arms = this.unionsById.get(unionId).arms;
|
|
4996
|
+
const join = B.newLabel("union.box.join"), none = B.newLabel("union.box.none");
|
|
4997
|
+
const labels = arms.map(() => B.newLabel("union.box.arm"));
|
|
4998
|
+
B.terminate(`switch i32 ${tag}, label %${none} [ ${labels.map((label, armTag) => `i32 ${armTag}, label %${label}`).join(" ")} ]`);
|
|
4999
|
+
const incoming = [];
|
|
5000
|
+
arms.forEach((arm, armTag) => {
|
|
5001
|
+
B.startBlock(labels[armTag]);
|
|
5002
|
+
let value;
|
|
5003
|
+
if (isUnitType(arm))
|
|
5004
|
+
value = this.unitInstanceRef(unionId, armTag);
|
|
5005
|
+
else {
|
|
5006
|
+
const payload = B.tmp();
|
|
5007
|
+
if (arm.kind === "bool")
|
|
5008
|
+
B.line(`${payload} = trunc i64 ${bits} to i1`);
|
|
5009
|
+
else
|
|
5010
|
+
B.line(`${payload} = bitcast i64 ${bits} to double`);
|
|
5011
|
+
value = this.unionNewOwned(unionId, armTag, { name: payload, type: arm });
|
|
5012
|
+
}
|
|
5013
|
+
incoming.push(`[ ${value}, %${B.currentLabel()} ]`);
|
|
5014
|
+
B.br(join);
|
|
5015
|
+
});
|
|
5016
|
+
B.startBlock(none);
|
|
5017
|
+
incoming.push(`[ null, %${none} ]`);
|
|
5018
|
+
B.br(join);
|
|
5019
|
+
B.startBlock(join);
|
|
5020
|
+
const box = B.tmp();
|
|
5021
|
+
B.line(`${box} = phi ptr ${incoming.join(", ")}`);
|
|
5022
|
+
return box;
|
|
5023
|
+
}
|
|
4733
5024
|
/** The i32 bits of a number proven an int32 (a direct call's i32
|
|
4734
5025
|
* argument or an i32 result): its exact integer when the value carries
|
|
4735
5026
|
* one, else the conversion the proof makes exact. */
|
|
@@ -4808,6 +5099,12 @@ export class LlEmitter {
|
|
|
4808
5099
|
canBorrowCallArgument(value) {
|
|
4809
5100
|
if (value.kind === "strLit")
|
|
4810
5101
|
return true;
|
|
5102
|
+
// An exact capsule owns its instance while the capsule's binding holds it.
|
|
5103
|
+
if (value.kind === "dynCheck" && value.exact)
|
|
5104
|
+
return value.value.kind === "varRef" && this.canBorrowCallArgument(value.value);
|
|
5105
|
+
// An inline union field has no box to lend.
|
|
5106
|
+
if (this.inlineFieldGet(value))
|
|
5107
|
+
return false;
|
|
4811
5108
|
// Class casts reinterpret the same pointer (prefix layouts).
|
|
4812
5109
|
if ((value.kind === "upcast" || value.kind === "downcast") &&
|
|
4813
5110
|
value.value.type.kind === "object")
|
|
@@ -5000,6 +5297,12 @@ export class LlEmitter {
|
|
|
5000
5297
|
this.finallyStack = savedFinally;
|
|
5001
5298
|
this.tryStack = savedTry;
|
|
5002
5299
|
}
|
|
5300
|
+
/** An async generator completing without a further turn: its request
|
|
5301
|
+
* settles as the body returns (scr_async_gen_hop_done). */
|
|
5302
|
+
emitAsyncGenSettled() {
|
|
5303
|
+
this.declare(`declare void @scr_async_gen_hop_done()`);
|
|
5304
|
+
this.B.line(`call void @scr_async_gen_hop_done()`);
|
|
5305
|
+
}
|
|
5003
5306
|
/** `return x` of a local whose slot is an owned scope entry of the same
|
|
5004
5307
|
* type: the return can take over the local's reference. */
|
|
5005
5308
|
movableReturn(value) {
|
|
@@ -5200,6 +5503,17 @@ export class LlEmitter {
|
|
|
5200
5503
|
this.scopes[this.scopes.length - 1].push({ slot: snapshot.sourceSlot, type: STRING }, { slot: snapshot.separatorSlot, type: STRING });
|
|
5201
5504
|
break;
|
|
5202
5505
|
}
|
|
5506
|
+
const stackObject = this.localStackObjects.get(s.localId);
|
|
5507
|
+
if (stackObject) {
|
|
5508
|
+
B.line(`store ptr ${emitStackObject(this, stackObject).name}, ptr ${b.slot}`);
|
|
5509
|
+
break;
|
|
5510
|
+
}
|
|
5511
|
+
if (s.init && this.reassignedStackObjects.has(s.localId)) {
|
|
5512
|
+
const slot = this.stackObjectSlot(s.localId, s.init.type);
|
|
5513
|
+
emitStackObject(this, s.init, slot);
|
|
5514
|
+
B.line(`store ptr ${slot}, ptr ${b.slot}`);
|
|
5515
|
+
break;
|
|
5516
|
+
}
|
|
5203
5517
|
const localUnion = this.localStackUnions.get(s.localId);
|
|
5204
5518
|
if (localUnion) {
|
|
5205
5519
|
const union = emitStackUnion(this, localUnion);
|
|
@@ -5303,6 +5617,24 @@ export class LlEmitter {
|
|
|
5303
5617
|
emitBorrowedArrayRead(this, s.init, b.slot);
|
|
5304
5618
|
break;
|
|
5305
5619
|
}
|
|
5620
|
+
const holeRead = this.loopArrayBorrows.has(s) ? dynHoleRead(s.init) : null;
|
|
5621
|
+
if (holeRead && s.init.kind === "ternary") {
|
|
5622
|
+
// A hole reads as the immortal undefined value, which needs no owner.
|
|
5623
|
+
const present = this.emitExpr(s.init.cond);
|
|
5624
|
+
const filled = B.newLabel("borrow.hole.filled"), missing = B.newLabel("borrow.hole.missing"), done = B.newLabel("borrow.hole.done");
|
|
5625
|
+
B.condBr(present.name, filled, missing);
|
|
5626
|
+
B.startBlock(filled);
|
|
5627
|
+
emitBorrowedArrayRead(this, holeRead, b.slot);
|
|
5628
|
+
B.br(done);
|
|
5629
|
+
B.startBlock(missing);
|
|
5630
|
+
this.declare("declare ptr @scr_dyn_undefined()");
|
|
5631
|
+
const undef = B.tmp();
|
|
5632
|
+
B.line(`${undef} = call ptr @scr_dyn_undefined()`);
|
|
5633
|
+
B.line(`store ptr ${undef}, ptr ${b.slot}`);
|
|
5634
|
+
B.br(done);
|
|
5635
|
+
B.startBlock(done);
|
|
5636
|
+
break;
|
|
5637
|
+
}
|
|
5306
5638
|
// A stable lexical alias cannot outlive its unchanged local owner.
|
|
5307
5639
|
// Whole-value uses still retain their own copies, so returning or
|
|
5308
5640
|
// storing the alias preserves the ordinary heap representation.
|
|
@@ -5347,15 +5679,23 @@ export class LlEmitter {
|
|
|
5347
5679
|
B.line(`store ptr ${v.name}, ptr ${owner}`);
|
|
5348
5680
|
break;
|
|
5349
5681
|
}
|
|
5682
|
+
if (this.reassignedStackObjects.has(s.localId)) {
|
|
5683
|
+
// The new value may read the old one: build it apart, then copy.
|
|
5684
|
+
const struct = stackObjectStruct(s.value.type);
|
|
5685
|
+
const value = emitStackObject(this, s.value);
|
|
5686
|
+
const bits = B.tmp();
|
|
5687
|
+
B.line(`${bits} = load ${struct}, ptr ${value.name}`);
|
|
5688
|
+
B.line(`store ${struct} ${bits}, ptr ${this.stackObjectSlot(s.localId, s.value.type)}`);
|
|
5689
|
+
break;
|
|
5690
|
+
}
|
|
5350
5691
|
const localStorage = this.localUnionStorage.get(s.localId);
|
|
5351
5692
|
if (localStorage) {
|
|
5352
5693
|
storeLocalUnion(this, localStorage, s.value);
|
|
5353
5694
|
break;
|
|
5354
5695
|
}
|
|
5355
|
-
const
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
this.emitStringSelfConcatAssign(s.localId, concat.left, suffix, false);
|
|
5696
|
+
const self = matchStringSelfConcat(s.localId, s.value);
|
|
5697
|
+
if (self) {
|
|
5698
|
+
this.emitStringSelfConcatAssign(s.localId, self.left, self.suffix, false);
|
|
5359
5699
|
break;
|
|
5360
5700
|
}
|
|
5361
5701
|
const b = this.binding(s.localId);
|
|
@@ -5520,24 +5860,17 @@ export class LlEmitter {
|
|
|
5520
5860
|
break;
|
|
5521
5861
|
}
|
|
5522
5862
|
const obj = this.emitStableReceiver(s.obj, [s.value]);
|
|
5523
|
-
const v = this.
|
|
5863
|
+
const v = this.emitFieldValue(s.value, s.kind === "recordSet"
|
|
5864
|
+
? this.recordFieldInline(s.shapeId, s.field)
|
|
5865
|
+
: this.inlineUnions.classField(s.className, s.field));
|
|
5524
5866
|
if (s.kind === "fieldSet")
|
|
5525
5867
|
this.emitStoreGuard(obj.name, s);
|
|
5526
5868
|
else if (this.publishedTypes?.recordGuarded(s.shapeId) === true)
|
|
5527
5869
|
this.emitPublishedFieldGuard(obj.name, null, s.field);
|
|
5528
|
-
const { ptr, type } = s.kind === "fieldSet"
|
|
5870
|
+
const { ptr, type, inline } = s.kind === "fieldSet"
|
|
5529
5871
|
? this.classFieldPtr(obj.name, s.className, s.field)
|
|
5530
5872
|
: this.recordFieldPtr(obj.name, s.shapeId, s.field);
|
|
5531
|
-
|
|
5532
|
-
this.moveTemp(v);
|
|
5533
|
-
const old = B.tmp();
|
|
5534
|
-
B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
5535
|
-
this.storeField(ptr, type, v.name);
|
|
5536
|
-
this.releaseValue(old, type);
|
|
5537
|
-
}
|
|
5538
|
-
else {
|
|
5539
|
-
this.storeField(ptr, type, v.name);
|
|
5540
|
-
}
|
|
5873
|
+
this.replaceField(ptr, type, inline, v);
|
|
5541
5874
|
if (s.kind === "fieldSet" &&
|
|
5542
5875
|
s.field === "name" &&
|
|
5543
5876
|
this.classMeta.get(s.className)?.root.def.name === "%Error") {
|
|
@@ -5638,15 +5971,20 @@ export class LlEmitter {
|
|
|
5638
5971
|
const lw = B.newLabel("rks.w");
|
|
5639
5972
|
B.condBr(pend, join, lw);
|
|
5640
5973
|
B.startBlock(lw);
|
|
5641
|
-
const { ptr, type } = this.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
5642
|
-
if (
|
|
5974
|
+
const { ptr, type, inline } = this.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
5975
|
+
if (inline) {
|
|
5976
|
+
// The slot copies the checked value's bits; nv is released below.
|
|
5977
|
+
this.storeField(ptr, type, nv, true);
|
|
5978
|
+
this.releaseValue(nv, type);
|
|
5979
|
+
}
|
|
5980
|
+
else if (isRefCounted(type)) {
|
|
5643
5981
|
const old = B.tmp();
|
|
5644
5982
|
B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
5645
|
-
this.storeField(ptr, type, nv);
|
|
5983
|
+
this.storeField(ptr, type, nv, false);
|
|
5646
5984
|
this.releaseValue(old, type);
|
|
5647
5985
|
}
|
|
5648
5986
|
else {
|
|
5649
|
-
this.storeField(ptr, type, nv);
|
|
5987
|
+
this.storeField(ptr, type, nv, false);
|
|
5650
5988
|
}
|
|
5651
5989
|
B.br(join);
|
|
5652
5990
|
B.startBlock(ln);
|
|
@@ -5669,15 +6007,20 @@ export class LlEmitter {
|
|
|
5669
6007
|
const ln = B.newLabel("rks.n");
|
|
5670
6008
|
B.condBr(hit, lh, ln);
|
|
5671
6009
|
B.startBlock(lh);
|
|
5672
|
-
const { ptr, type } = this.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
5673
|
-
if (
|
|
6010
|
+
const { ptr, type, inline } = this.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
6011
|
+
if (inline) {
|
|
6012
|
+
// The write owns the moved-in value; the slot copies its bits.
|
|
6013
|
+
this.storeField(ptr, type, v.name, true);
|
|
6014
|
+
this.releaseValue(v.name, type);
|
|
6015
|
+
}
|
|
6016
|
+
else if (isRefCounted(type)) {
|
|
5674
6017
|
const old = B.tmp();
|
|
5675
6018
|
B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
5676
|
-
this.storeField(ptr, type, v.name);
|
|
6019
|
+
this.storeField(ptr, type, v.name, false);
|
|
5677
6020
|
this.releaseValue(old, type);
|
|
5678
6021
|
}
|
|
5679
6022
|
else {
|
|
5680
|
-
this.storeField(ptr, type, v.name);
|
|
6023
|
+
this.storeField(ptr, type, v.name, false);
|
|
5681
6024
|
}
|
|
5682
6025
|
B.br(join);
|
|
5683
6026
|
B.startBlock(ln);
|
|
@@ -6199,8 +6542,16 @@ export class LlEmitter {
|
|
|
6199
6542
|
break;
|
|
6200
6543
|
}
|
|
6201
6544
|
let v = null;
|
|
6202
|
-
const moved = this.finallyStack.length === 0
|
|
6203
|
-
|
|
6545
|
+
const moved = this.finallyStack.length === 0 && !this.currentUnionResult
|
|
6546
|
+
? this.movableReturn(s.value)
|
|
6547
|
+
: null;
|
|
6548
|
+
if (s.value !== null && this.currentUnionResult) {
|
|
6549
|
+
// The tag and payload bits leave in registers; a heap box the
|
|
6550
|
+
// value needed is released with its frame below.
|
|
6551
|
+
const box = this.emitUnionProjection(s.value);
|
|
6552
|
+
v = { name: this.scalarUnionPair(box.name, s.value.type), type: s.value.type };
|
|
6553
|
+
}
|
|
6554
|
+
else if (moved !== null) {
|
|
6204
6555
|
// Returning an owned local hands its reference to the caller: no
|
|
6205
6556
|
// retain now and no release of the local below.
|
|
6206
6557
|
const t = B.tmp();
|
|
@@ -6230,9 +6581,22 @@ export class LlEmitter {
|
|
|
6230
6581
|
v = this.emitExpr(s.value);
|
|
6231
6582
|
this.moveTemp(v);
|
|
6232
6583
|
}
|
|
6584
|
+
// An async generator's `return v` awaits v before any crossed
|
|
6585
|
+
// finally runs. Past finally regions that turn is taken here and
|
|
6586
|
+
// the request settles at completion; otherwise the completion's
|
|
6587
|
+
// own turn is the await (nothing runs in between).
|
|
6588
|
+
const genSettles = this.currentAsyncGenerator && (s.awaited === true || this.finallyStack.length > 0);
|
|
6589
|
+
if (this.currentAsyncGenerator && s.awaited !== true && this.finallyStack.length > 0) {
|
|
6590
|
+
if (this.wasi)
|
|
6591
|
+
this.emitWasiSuspend(null);
|
|
6592
|
+
else {
|
|
6593
|
+
this.declare(`declare void @scr_await_hop()`);
|
|
6594
|
+
B.line(`call void @scr_await_hop()`);
|
|
6595
|
+
}
|
|
6596
|
+
}
|
|
6233
6597
|
if (this.finallyStack.length > 0) {
|
|
6234
6598
|
let pretSlot = null;
|
|
6235
|
-
if (v !== null && isRefCounted(v.type)) {
|
|
6599
|
+
if (v !== null && isRefCounted(v.type) && !this.currentUnionResult) {
|
|
6236
6600
|
pretSlot = B.slot();
|
|
6237
6601
|
B.entryAllocas.push(`${pretSlot} = alloca ptr ; pending return (through finally)`);
|
|
6238
6602
|
B.line(`store ptr ${v.name}, ptr ${pretSlot}`);
|
|
@@ -6265,6 +6629,8 @@ export class LlEmitter {
|
|
|
6265
6629
|
this.releaseForJump(0, 0);
|
|
6266
6630
|
}
|
|
6267
6631
|
if (!B.isTerminated()) {
|
|
6632
|
+
if (genSettles)
|
|
6633
|
+
this.emitAsyncGenSettled();
|
|
6268
6634
|
if (this.currentCoro !== null) {
|
|
6269
6635
|
this.emitWasiFulfill(v);
|
|
6270
6636
|
B.terminate(`br label %${this.currentCoro.finalLabel}`);
|
|
@@ -6273,6 +6639,8 @@ export class LlEmitter {
|
|
|
6273
6639
|
B.terminate("ret void");
|
|
6274
6640
|
else if (this.currentInt32Result)
|
|
6275
6641
|
B.terminate(`ret i32 ${this.int32Argument(v, s.value)}`);
|
|
6642
|
+
else if (this.currentUnionResult)
|
|
6643
|
+
B.terminate(`ret ${SCALAR_UNION_RESULT} ${v.name}`);
|
|
6276
6644
|
else
|
|
6277
6645
|
B.terminate(`ret ${this.llType(s.value.type)} ${v.name}`);
|
|
6278
6646
|
}
|
|
@@ -6313,7 +6681,7 @@ export class LlEmitter {
|
|
|
6313
6681
|
break;
|
|
6314
6682
|
default: {
|
|
6315
6683
|
// Statement coverage is now total (bytesSet closed the set) —
|
|
6316
|
-
// keep
|
|
6684
|
+
// keep throwing LlvmUnsupportedError for any future IR statement kind.
|
|
6317
6685
|
const rest = s;
|
|
6318
6686
|
const k = rest.kind;
|
|
6319
6687
|
throw new LlvmUnsupportedError(`stmt:${k}`, rest.loc);
|
|
@@ -6659,7 +7027,11 @@ export class LlEmitter {
|
|
|
6659
7027
|
if (e.kind === "seqExpr" &&
|
|
6660
7028
|
isRefCounted(e.result.type) &&
|
|
6661
7029
|
e.result.kind !== "strLit" &&
|
|
6662
|
-
this.discardableRead(e.result)
|
|
7030
|
+
(this.discardableRead(e.result) ||
|
|
7031
|
+
// A function-local binding's read has no effect of its own (a
|
|
7032
|
+
// compound assignment's result, say); a module binding's read may
|
|
7033
|
+
// throw before initialization, so it stays.
|
|
7034
|
+
(e.result.kind === "varRef" && this.binding(e.result.localId).kind === "local"))) {
|
|
6663
7035
|
this.emitSequence(() => {
|
|
6664
7036
|
for (const s of e.stmts)
|
|
6665
7037
|
this.emitStmt(s);
|
|
@@ -6690,8 +7062,11 @@ export class LlEmitter {
|
|
|
6690
7062
|
// of first building the suffix as a separate string.
|
|
6691
7063
|
const parts = stringParts(suffix);
|
|
6692
7064
|
const mixed = parts.length > 1 || numberPart(parts[0]) !== null;
|
|
7065
|
+
const charCode = mixed ? null : this.emitSingleCharCode(suffix);
|
|
6693
7066
|
const inputs = mixed ? emitConcatInputs(this, parts) : [];
|
|
6694
|
-
|
|
7067
|
+
// The concat only reads the suffix; relinquishing the binding below
|
|
7068
|
+
// runs no code that could rebind a borrowed local.
|
|
7069
|
+
const right = mixed || charCode !== null ? null : emitStringInputs(this, [suffix])[0];
|
|
6695
7070
|
const b = this.binding(localId);
|
|
6696
7071
|
const B = this.B;
|
|
6697
7072
|
if (b.kind === "boxed") {
|
|
@@ -6705,7 +7080,14 @@ export class LlEmitter {
|
|
|
6705
7080
|
this.releaseValue(old, b.type);
|
|
6706
7081
|
}
|
|
6707
7082
|
let raw;
|
|
6708
|
-
if (
|
|
7083
|
+
if (charCode !== null) {
|
|
7084
|
+
// The snapshot moves into the consuming character append.
|
|
7085
|
+
this.moveTemp(snapshot);
|
|
7086
|
+
this.declare(`declare ptr @scr_str_concat_move_char_code(ptr, double)`);
|
|
7087
|
+
raw = B.tmp();
|
|
7088
|
+
B.line(`${raw} = call ptr @scr_str_concat_move_char_code(ptr ${snapshot.name}, double ${charCode.name})`);
|
|
7089
|
+
}
|
|
7090
|
+
else if (right === null) {
|
|
6709
7091
|
raw = emitMixedConcat(this, snapshot.name, inputs);
|
|
6710
7092
|
}
|
|
6711
7093
|
else {
|
|
@@ -6730,6 +7112,17 @@ export class LlEmitter {
|
|
|
6730
7112
|
}
|
|
6731
7113
|
return result;
|
|
6732
7114
|
}
|
|
7115
|
+
/** The code of a one-argument `String.fromCharCode(c)` suffix, emitted, so
|
|
7116
|
+
* `s += String.fromCharCode(c)` appends the character without building
|
|
7117
|
+
* the one-character string; null for any other suffix. */
|
|
7118
|
+
emitSingleCharCode(suffix) {
|
|
7119
|
+
if (suffix.kind !== "libCall" || suffix.fn !== "string.fromCharCode")
|
|
7120
|
+
return null;
|
|
7121
|
+
const packed = suffix.args[0];
|
|
7122
|
+
if (packed?.kind !== "arrayLit" || packed.elems.length !== 1 || packed.spreads?.length)
|
|
7123
|
+
return null;
|
|
7124
|
+
return this.emitExpr(packed.elems[0]);
|
|
7125
|
+
}
|
|
6733
7126
|
/** `local = local + suffix` when the suffix cannot read or write the
|
|
6734
7127
|
* local (an unboxed binding is only reachable through this function's own
|
|
6735
7128
|
* expressions): reading the binding after the suffix gives the value the
|
|
@@ -6749,14 +7142,21 @@ export class LlEmitter {
|
|
|
6749
7142
|
return null;
|
|
6750
7143
|
const parts = stringParts(suffix);
|
|
6751
7144
|
const mixed = parts.length > 1 || numberPart(parts[0]) !== null;
|
|
7145
|
+
const charCode = mixed ? null : this.emitSingleCharCode(suffix);
|
|
6752
7146
|
const inputs = mixed ? emitConcatInputs(this, parts) : [];
|
|
6753
|
-
|
|
7147
|
+
// The concat only reads the suffix, which may stay borrowed.
|
|
7148
|
+
const right = mixed || charCode !== null ? null : emitStringInputs(this, [suffix])[0];
|
|
6754
7149
|
this.materializeSplitLocal(localId);
|
|
6755
7150
|
const B = this.B;
|
|
6756
7151
|
const head = B.tmp();
|
|
6757
7152
|
B.line(`${head} = load ptr, ptr ${b.slot}`);
|
|
6758
7153
|
let raw;
|
|
6759
|
-
if (
|
|
7154
|
+
if (charCode !== null) {
|
|
7155
|
+
this.declare(`declare ptr @scr_str_concat_move_char_code(ptr, double)`);
|
|
7156
|
+
raw = B.tmp();
|
|
7157
|
+
B.line(`${raw} = call ptr @scr_str_concat_move_char_code(ptr ${head}, double ${charCode.name})`);
|
|
7158
|
+
}
|
|
7159
|
+
else if (right === null) {
|
|
6760
7160
|
raw = emitMixedConcat(this, head, inputs, true);
|
|
6761
7161
|
}
|
|
6762
7162
|
else {
|
|
@@ -6787,8 +7187,45 @@ export class LlEmitter {
|
|
|
6787
7187
|
emitIntrinsicExpr(e) {
|
|
6788
7188
|
if (e.name === "threads.publish")
|
|
6789
7189
|
return this.emitPublish(e);
|
|
7190
|
+
if (e.name === "region.create" ||
|
|
7191
|
+
e.name === "region.enter" ||
|
|
7192
|
+
e.name === "region.leave" ||
|
|
7193
|
+
e.name === "region.release")
|
|
7194
|
+
return this.emitRegionIntrinsic(e);
|
|
6790
7195
|
return emitIntrinsicExpr(this, e);
|
|
6791
7196
|
}
|
|
7197
|
+
/** Lifetime regions in modules with lifetimeRegions (llvm/regions.ts).
|
|
7198
|
+
* Created with the class graph; null elsewhere. */
|
|
7199
|
+
regions = null;
|
|
7200
|
+
/** LifetimeRegion's runtime calls: create answers the region id, enter
|
|
7201
|
+
* and leave bracket run(), release condemns. */
|
|
7202
|
+
emitRegionIntrinsic(e) {
|
|
7203
|
+
if (this.regions === null)
|
|
7204
|
+
throw new InternalCompilerError(`llvm emitter bug: ${e.name} without lifetimeRegions`);
|
|
7205
|
+
const args = e.args.map((a) => this.emitExpr(a));
|
|
7206
|
+
if (this.B.isTerminated())
|
|
7207
|
+
return { name: "", type: e.type };
|
|
7208
|
+
switch (e.name) {
|
|
7209
|
+
case "region.create": {
|
|
7210
|
+
this.declare(`declare double @scr_region_create(ptr)`);
|
|
7211
|
+
const id = this.B.tmp();
|
|
7212
|
+
this.B.line(`${id} = call double @scr_region_create(ptr ${REGION_TYPES})`);
|
|
7213
|
+
return { name: id, type: e.type };
|
|
7214
|
+
}
|
|
7215
|
+
case "region.enter":
|
|
7216
|
+
this.declare(`declare void @scr_region_enter(double)`);
|
|
7217
|
+
this.B.line(`call void @scr_region_enter(double ${args[0].name})`);
|
|
7218
|
+
break;
|
|
7219
|
+
case "region.leave":
|
|
7220
|
+
this.declare(`declare void @scr_region_leave()`);
|
|
7221
|
+
this.B.line(`call void @scr_region_leave()`);
|
|
7222
|
+
break;
|
|
7223
|
+
default:
|
|
7224
|
+
this.declare(`declare void @scr_region_release(double)`);
|
|
7225
|
+
this.B.line(`call void @scr_region_release(double ${args[0].name})`);
|
|
7226
|
+
}
|
|
7227
|
+
return { name: "", type: e.type };
|
|
7228
|
+
}
|
|
6792
7229
|
publishWalkersCache = null;
|
|
6793
7230
|
/** Per-type publication walkers, created on the first publish. */
|
|
6794
7231
|
get publishWalkers() {
|
|
@@ -6802,6 +7239,7 @@ export class LlEmitter {
|
|
|
6802
7239
|
tracedShapes: this.tracedShapes,
|
|
6803
7240
|
unionsById: this.unionsById,
|
|
6804
7241
|
recordsById: this.recordsById,
|
|
7242
|
+
inlineUnions: this.inlineUnions,
|
|
6805
7243
|
nullableArm: (t) => this.nullableUnions.of(t)?.arm ?? null,
|
|
6806
7244
|
classInfo: (className) => {
|
|
6807
7245
|
const meta = this.classMetaOf(className);
|
|
@@ -6811,11 +7249,16 @@ export class LlEmitter {
|
|
|
6811
7249
|
pre: meta.pre,
|
|
6812
7250
|
post: meta.post,
|
|
6813
7251
|
runtimeRooted: meta.root.def.runtime === true,
|
|
6814
|
-
fields:
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
7252
|
+
// Inline scalar-union fields are plain bits: nothing to push.
|
|
7253
|
+
fields: meta.def.fields.flatMap((f) => this.inlineUnions.classField(className, f.name)
|
|
7254
|
+
? []
|
|
7255
|
+
: [
|
|
7256
|
+
{
|
|
7257
|
+
name: f.name,
|
|
7258
|
+
index: classFieldIndex(meta, f.name).index,
|
|
7259
|
+
type: this.nullableFields.storageType(className, f.name, f.type),
|
|
7260
|
+
},
|
|
7261
|
+
]),
|
|
6819
7262
|
};
|
|
6820
7263
|
},
|
|
6821
7264
|
classesInInterval: (pre, post) => byPre.filter((m) => m.pre >= pre && m.pre <= post).map((m) => m.def.name),
|
|
@@ -6982,6 +7425,8 @@ export class LlEmitter {
|
|
|
6982
7425
|
this.B.line(`${value} = load ptr, ptr ${binding.slot}`);
|
|
6983
7426
|
return { name: value, type: e.type };
|
|
6984
7427
|
}
|
|
7428
|
+
if (e.kind === "dynCheck" && e.exact)
|
|
7429
|
+
return this.emitExactCapsuleObject(e.value, e.type);
|
|
6985
7430
|
if (e.kind === "chainRecv") {
|
|
6986
7431
|
// The chain's bind slot holds its receiver unchanged until the body
|
|
6987
7432
|
// finishes, owned by the slot itself or by the chain's receiver.
|
|
@@ -7042,13 +7487,14 @@ export class LlEmitter {
|
|
|
7042
7487
|
if (e.kind === "recordGet" || e.kind === "fieldGet") {
|
|
7043
7488
|
const receiver = this.emitReadReceiver(e.obj);
|
|
7044
7489
|
if (e.kind === "recordGet") {
|
|
7045
|
-
|
|
7046
|
-
|
|
7490
|
+
// An inline union field answers a private stack box.
|
|
7491
|
+
const { ptr, type, inline } = this.recordFieldPtr(receiver.name, e.shapeId, e.field);
|
|
7492
|
+
return { name: this.loadRecordField(ptr, type, inline), type: e.type };
|
|
7047
7493
|
}
|
|
7048
|
-
const { ptr, type } = this.classFieldPtr(receiver.name, e.className, e.field);
|
|
7494
|
+
const { ptr, type, inline } = this.classFieldPtr(receiver.name, e.className, e.field);
|
|
7049
7495
|
if (this.int32Slots.isField(e.className, e.field))
|
|
7050
7496
|
return this.loadInt32Field(ptr, e.type);
|
|
7051
|
-
return { name: this.loadField(ptr, type), type: e.type };
|
|
7497
|
+
return { name: this.loadField(ptr, type, inline), type: e.type };
|
|
7052
7498
|
}
|
|
7053
7499
|
if (e.kind === "ternary" && this.canBorrowReceiver(e.then) && this.canBorrowReceiver(e.else_)) {
|
|
7054
7500
|
// Checked projections lower to a ternary with an always-throwing
|
|
@@ -7075,10 +7521,30 @@ export class LlEmitter {
|
|
|
7075
7521
|
B.line(`${value} = load ptr, ptr ${slot}`);
|
|
7076
7522
|
return { name: value, type: e.type };
|
|
7077
7523
|
}
|
|
7524
|
+
// Scalar optional values and register results answer a private stack
|
|
7525
|
+
// box. A ternary of borrowable arms above keeps lending its arm.
|
|
7526
|
+
if ((e.kind === "optChain" ||
|
|
7527
|
+
e.kind === "nullish" ||
|
|
7528
|
+
e.kind === "ternary" ||
|
|
7529
|
+
e.kind === "arrIntrinsic") &&
|
|
7530
|
+
isScalarOptionalSource(e, this.unionSources))
|
|
7531
|
+
return emitScalarOptional(this, e);
|
|
7532
|
+
if (e.kind === "call" && this.scalarResultCall(e))
|
|
7533
|
+
return emitCallExpr(this, e, false, true);
|
|
7078
7534
|
if (e.kind === "call" && this.canBorrowReceiver(e))
|
|
7079
7535
|
return emitBorrowedResultCall(this, e);
|
|
7080
7536
|
return this.emitExpr(e);
|
|
7081
7537
|
}
|
|
7538
|
+
/** The frame slot a reassigned stack-object local keeps for its value. */
|
|
7539
|
+
stackObjectSlot(localId, type) {
|
|
7540
|
+
let slot = this.stackObjectSlots.get(localId);
|
|
7541
|
+
if (slot === undefined) {
|
|
7542
|
+
slot = this.B.slot();
|
|
7543
|
+
this.B.entryAllocas.push(`${slot} = alloca ${stackObjectStruct(type)}, align 8`);
|
|
7544
|
+
this.stackObjectSlots.set(localId, slot);
|
|
7545
|
+
}
|
|
7546
|
+
return slot;
|
|
7547
|
+
}
|
|
7082
7548
|
/** A private stack union source with an independently owned payload. */
|
|
7083
7549
|
canStackReceiver(e) {
|
|
7084
7550
|
return this.isStackUnionSource(e);
|
|
@@ -7090,7 +7556,17 @@ export class LlEmitter {
|
|
|
7090
7556
|
return false;
|
|
7091
7557
|
return (canStackUnion(e, this.boxedUnionsById) ||
|
|
7092
7558
|
matchMapRead(e, this.boxedUnionsById) !== null ||
|
|
7093
|
-
this.optionalArrayReads.get(e) !== null
|
|
7559
|
+
this.optionalArrayReads.get(e) !== null ||
|
|
7560
|
+
isScalarOptionalSource(e, this.unionSources) ||
|
|
7561
|
+
this.scalarResultCall(e) ||
|
|
7562
|
+
this.inlineFieldGet(e));
|
|
7563
|
+
}
|
|
7564
|
+
/** A read of a record or class field that stores its scalar union
|
|
7565
|
+
* inline. */
|
|
7566
|
+
inlineFieldGet(e) {
|
|
7567
|
+
if (e.kind === "recordGet")
|
|
7568
|
+
return this.recordFieldInline(e.shapeId, e.field);
|
|
7569
|
+
return e.kind === "fieldGet" && this.inlineUnions.classField(e.className, e.field);
|
|
7094
7570
|
}
|
|
7095
7571
|
/** The nullable-pointer representation behind a union-typed class field
|
|
7096
7572
|
* read, or null for every other expression. */
|
|
@@ -7229,6 +7705,15 @@ export class LlEmitter {
|
|
|
7229
7705
|
this.localArrayReads.has(localId) ||
|
|
7230
7706
|
this.mapReadLifetimes.locals.has(localId));
|
|
7231
7707
|
}
|
|
7708
|
+
/** The instance of a capsule known to hold exactly this class (borrowed). */
|
|
7709
|
+
emitExactCapsuleObject(value, type) {
|
|
7710
|
+
const capsule = this.emitReadReceiver(value);
|
|
7711
|
+
const slot = this.B.tmp();
|
|
7712
|
+
const object = this.B.tmp();
|
|
7713
|
+
this.B.line(`${slot} = getelementptr inbounds i8, ptr ${capsule.name}, i64 16 ; ->v.typed_ref.ptr`);
|
|
7714
|
+
this.B.line(`${object} = load ptr, ptr ${slot}`);
|
|
7715
|
+
return { name: object, type };
|
|
7716
|
+
}
|
|
7232
7717
|
canBorrowReceiver(e) {
|
|
7233
7718
|
switch (e.kind) {
|
|
7234
7719
|
case "chainRecv":
|
|
@@ -7246,9 +7731,11 @@ export class LlEmitter {
|
|
|
7246
7731
|
case "downcast":
|
|
7247
7732
|
case "upcast":
|
|
7248
7733
|
return this.canBorrowReceiver(e.value);
|
|
7734
|
+
// An inline union field has no box to lend: projections read it
|
|
7735
|
+
// through emitReadReceiver's private stack box.
|
|
7249
7736
|
case "fieldGet":
|
|
7250
7737
|
case "recordGet":
|
|
7251
|
-
return this.canBorrowReceiver(e.obj);
|
|
7738
|
+
return !this.inlineFieldGet(e) && this.canBorrowReceiver(e.obj);
|
|
7252
7739
|
case "ternary":
|
|
7253
7740
|
return this.canBorrowReceiver(e.then) && this.canBorrowReceiver(e.else_);
|
|
7254
7741
|
case "seqExpr": {
|
|
@@ -7484,8 +7971,11 @@ export class LlEmitter {
|
|
|
7484
7971
|
fsRenameThunkFor(cbT) {
|
|
7485
7972
|
return fsRenameThunkFor(this, cbT);
|
|
7486
7973
|
}
|
|
7487
|
-
cryptoBytesThunkFor(cbT, arrayBuffer = false) {
|
|
7488
|
-
return cryptoBytesThunkFor(this, cbT, arrayBuffer);
|
|
7974
|
+
cryptoBytesThunkFor(cbT, arrayBuffer = false, valueMode = "buffer") {
|
|
7975
|
+
return cryptoBytesThunkFor(this, cbT, arrayBuffer, valueMode);
|
|
7976
|
+
}
|
|
7977
|
+
cryptoIntThunkFor(cbT) {
|
|
7978
|
+
return cryptoIntThunkFor(this, cbT);
|
|
7489
7979
|
}
|
|
7490
7980
|
zlibBytesThunkFor(cbT) {
|
|
7491
7981
|
return zlibBytesThunkFor(this, cbT);
|