@scriptc/compiler 0.3.2 → 0.3.4
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 +1202 -64
- package/dist/backend/cycle-analysis.js +6 -1
- package/dist/backend/cycle-analysis.js.map +1 -1
- package/dist/backend/cycle-mutability.d.ts +5 -0
- package/dist/backend/cycle-mutability.js +62 -3
- package/dist/backend/cycle-mutability.js.map +1 -1
- package/dist/backend/executable-features.js +1 -0
- package/dist/backend/executable-features.js.map +1 -1
- package/dist/backend/library-pack.js +1 -0
- package/dist/backend/library-pack.js.map +1 -1
- package/dist/backend/llvm/alloc.js +24 -10
- package/dist/backend/llvm/alloc.js.map +1 -1
- package/dist/backend/llvm/alloc.test.js +47 -1
- package/dist/backend/llvm/alloc.test.js.map +1 -1
- 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 +12 -1
- package/dist/backend/llvm/call-lifetimes.js +41 -11
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +85 -1
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/classes.js +87 -36
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +6 -1
- package/dist/backend/llvm/common.js +8 -1
- package/dist/backend/llvm/common.js.map +1 -1
- package/dist/backend/llvm/dense-array-access.d.ts +5 -0
- package/dist/backend/llvm/dense-array-access.js +3 -3
- package/dist/backend/llvm/dense-array-access.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +44 -1
- package/dist/backend/llvm/dyn.js +251 -36
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +77 -14
- package/dist/backend/llvm/emitter.js +461 -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 +52 -1
- package/dist/backend/llvm/expr-async.js.map +1 -1
- package/dist/backend/llvm/expr-bytes.d.ts +9 -0
- package/dist/backend/llvm/expr-bytes.js +169 -63
- package/dist/backend/llvm/expr-bytes.js.map +1 -1
- package/dist/backend/llvm/expr-callbacks.js +16 -2
- package/dist/backend/llvm/expr-callbacks.js.map +1 -1
- package/dist/backend/llvm/expr-calls.d.ts +3 -1
- package/dist/backend/llvm/expr-calls.js +57 -2
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +57 -19
- package/dist/backend/llvm/expr-containers.js.map +1 -1
- package/dist/backend/llvm/expr-dynamic.js +19 -8
- package/dist/backend/llvm/expr-dynamic.js.map +1 -1
- package/dist/backend/llvm/expr-primitives.js +28 -30
- package/dist/backend/llvm/expr-primitives.js.map +1 -1
- package/dist/backend/llvm/expr-records.js +8 -4
- package/dist/backend/llvm/expr-records.js.map +1 -1
- package/dist/backend/llvm/expr-stream-bridges.js +35 -32
- package/dist/backend/llvm/expr-stream-bridges.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/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/intern-tables.test.d.ts +1 -0
- package/dist/backend/llvm/intern-tables.test.js +77 -0
- package/dist/backend/llvm/intern-tables.test.js.map +1 -0
- package/dist/backend/llvm/lib-datagram.js +10 -0
- package/dist/backend/llvm/lib-datagram.js.map +1 -1
- package/dist/backend/llvm/lib-dispatch.js +255 -29
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +176 -7
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-network.js +25 -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.d.ts +5 -0
- package/dist/backend/llvm/lib-shared.js +212 -1
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +184 -0
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/lib-test.js +9 -0
- package/dist/backend/llvm/lib-test.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +7 -3
- 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 +2 -0
- package/dist/backend/llvm/local-union-storage.js +5 -0
- package/dist/backend/llvm/local-union-storage.js.map +1 -1
- package/dist/backend/llvm/local-union-storage.test.js +1 -0
- 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 +24 -0
- package/dist/backend/llvm/map-number-lookup.js +88 -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 +158 -0
- package/dist/backend/llvm/map-number-lookup.test.js.map +1 -0
- package/dist/backend/llvm/map-read-lifetimes.d.ts +9 -0
- package/dist/backend/llvm/map-read-lifetimes.js +90 -1
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js +129 -1
- package/dist/backend/llvm/map-read-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/publish.d.ts +9 -0
- package/dist/backend/llvm/publish.js +25 -4
- package/dist/backend/llvm/publish.js.map +1 -1
- package/dist/backend/llvm/record-results.d.ts +8 -5
- package/dist/backend/llvm/record-results.js +20 -12
- package/dist/backend/llvm/record-results.js.map +1 -1
- package/dist/backend/llvm/reference-effects.js +13 -0
- package/dist/backend/llvm/reference-effects.js.map +1 -1
- package/dist/backend/llvm/reference-writes.js +19 -2
- package/dist/backend/llvm/reference-writes.js.map +1 -1
- package/dist/backend/llvm/regions.d.ts +5 -1
- package/dist/backend/llvm/regions.js +24 -10
- package/dist/backend/llvm/regions.js.map +1 -1
- 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 +56 -10
- package/dist/backend/llvm/shapes.js +178 -39
- package/dist/backend/llvm/shapes.js.map +1 -1
- package/dist/backend/llvm/shapes.test.js +61 -3
- package/dist/backend/llvm/shapes.test.js.map +1 -1
- package/dist/backend/llvm/stack-objects.js +16 -4
- package/dist/backend/llvm/stack-objects.js.map +1 -1
- package/dist/backend/llvm/stack-objects.test.js +3 -0
- package/dist/backend/llvm/stack-objects.test.js.map +1 -1
- package/dist/backend/llvm/string-reads.js +2 -2
- package/dist/backend/llvm/string-reads.js.map +1 -1
- package/dist/backend/llvm/string-slices.js +2 -2
- package/dist/backend/llvm/string-slices.js.map +1 -1
- package/dist/backend/llvm/walkers.d.ts +11 -0
- package/dist/backend/llvm/walkers.js +106 -10
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/backend/may-throw.js +13 -4
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +5 -2
- package/dist/backend/native/executable.js +27 -8
- package/dist/backend/native/executable.js.map +1 -1
- package/dist/backend/native/runtime-inputs.d.ts +1 -1
- package/dist/backend/native/runtime-inputs.js +2 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-codegen-core.d.ts +4 -4
- package/dist/backend/native-codegen-core.js +4 -6
- package/dist/backend/native-codegen-core.js.map +1 -1
- package/dist/backend/native-codegen.test.js +7 -8
- package/dist/backend/native-codegen.test.js.map +1 -1
- package/dist/backend/native-link-info-core.d.ts +3 -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/publication.js +3 -1
- package/dist/backend/publication.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-targets.test.js +2 -1
- package/dist/backend/runtime-pack-targets.test.js.map +1 -1
- package/dist/backend/runtime-pack.test.js +2 -1
- package/dist/backend/runtime-pack.test.js.map +1 -1
- package/dist/backend/target-diagnostics.js +11 -1
- package/dist/backend/target-diagnostics.js.map +1 -1
- package/dist/backend/target-diagnostics.test.js +4 -1
- package/dist/backend/target-diagnostics.test.js.map +1 -1
- package/dist/backend/warm-cache.js +1 -0
- package/dist/backend/warm-cache.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 +1 -0
- package/dist/executable/executable-cache.js.map +1 -1
- package/dist/executable/executable-cache.test.js +1 -0
- package/dist/executable/executable-cache.test.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 +5 -1
- package/dist/frontend/experimental-import.js +28 -3
- package/dist/frontend/experimental-import.js.map +1 -1
- package/dist/frontend/lowering/assert-instances.d.ts +38 -0
- package/dist/frontend/lowering/assert-instances.js +269 -0
- package/dist/frontend/lowering/assert-instances.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/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.d.ts +18 -0
- package/dist/frontend/lowering/builtins/compression.js +178 -4
- package/dist/frontend/lowering/builtins/compression.js.map +1 -1
- package/dist/frontend/lowering/builtins/constants.js +7 -2
- package/dist/frontend/lowering/builtins/constants.js.map +1 -1
- package/dist/frontend/lowering/builtins/crypto.d.ts +6 -0
- package/dist/frontend/lowering/builtins/crypto.js +526 -121
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
- package/dist/frontend/lowering/builtins/errors.js +23 -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/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 +44 -11
- package/dist/frontend/lowering/builtins/module-calls.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 +107 -14
- package/dist/frontend/lowering/builtins/process.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/timers.d.ts +3 -0
- package/dist/frontend/lowering/builtins/timers.js +109 -23
- package/dist/frontend/lowering/builtins/timers.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 +26 -2
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +2 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +171 -13
- 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 +4 -7
- package/dist/frontend/lowering/containers/array-callbacks.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/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/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/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 +16 -12
- package/dist/frontend/lowering/expressions/object-literals.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/intern-tables.d.ts +13 -0
- package/dist/frontend/lowering/intern-tables.js +536 -0
- package/dist/frontend/lowering/intern-tables.js.map +1 -0
- package/dist/frontend/lowering/lower-array-sort.d.ts +12 -1
- package/dist/frontend/lowering/lower-array-sort.js +561 -191
- package/dist/frontend/lowering/lower-array-sort.js.map +1 -1
- package/dist/frontend/lowering/lower-array-sort.test.js +4 -2
- package/dist/frontend/lowering/lower-array-sort.test.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +702 -63
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-async-iteration.d.ts +6 -3
- package/dist/frontend/lowering/lower-async-iteration.js +259 -4
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +118 -12
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +11 -2
- package/dist/frontend/lowering/lower-classes.js +76 -9
- 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-dgram.js +77 -52
- package/dist/frontend/lowering/lower-dgram.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 +124 -22
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.d.ts +6 -0
- package/dist/frontend/lowering/lower-inspect.js +240 -49
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +1 -1
- package/dist/frontend/lowering/lower-mock.d.ts +11 -0
- package/dist/frontend/lowering/lower-mock.js +504 -0
- package/dist/frontend/lowering/lower-mock.js.map +1 -0
- package/dist/frontend/lowering/lower-modules.d.ts +1 -1
- package/dist/frontend/lowering/lower-modules.js +14 -3
- 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.d.ts +3 -0
- package/dist/frontend/lowering/lower-server.js +419 -44
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stdlib.d.ts +7 -1
- package/dist/frontend/lowering/lower-stdlib.js +10 -3
- 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 +69 -14
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.d.ts +10 -6
- package/dist/frontend/lowering/lower-stream.js +1020 -49
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-test.js +86 -8
- package/dist/frontend/lowering/lower-test.js.map +1 -1
- package/dist/frontend/lowering/lower-timers.js +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +45 -5
- package/dist/frontend/lowering/lowerer.js +317 -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/pairs-snapshot.d.ts +6 -0
- package/dist/frontend/lowering/pairs-snapshot.js +49 -0
- package/dist/frontend/lowering/pairs-snapshot.js.map +1 -1
- 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 +11 -3
- package/dist/frontend/lowering/surfaces.js +334 -37
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/lowering/zlib-constants.d.ts +1 -0
- package/dist/frontend/lowering/zlib-constants.js +181 -0
- package/dist/frontend/lowering/zlib-constants.js.map +1 -0
- package/dist/frontend/mock-shapes.d.ts +10 -0
- package/dist/frontend/mock-shapes.js +76 -0
- package/dist/frontend/mock-shapes.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 +3 -3
- package/dist/frontend/program.js +25 -18
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.d.ts +4 -0
- package/dist/frontend/resolve.js +15 -1
- package/dist/frontend/resolve.js.map +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 +3 -2
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +21 -1
- package/dist/frontend/type-mapper.js +245 -27
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.js +7 -5
- 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 +115 -0
- package/dist/ir/builtin-effects.js.map +1 -1
- package/dist/ir/builtin-signatures.d.ts +1 -1
- package/dist/ir/builtin-signatures.js +438 -46
- package/dist/ir/builtin-signatures.js.map +1 -1
- package/dist/ir/int32-slots.js +1 -0
- package/dist/ir/int32-slots.js.map +1 -1
- package/dist/ir/ir.d.ts +84 -17
- package/dist/ir/ir.js +54 -1
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/runtime-features.d.ts +1 -0
- package/dist/ir/runtime-features.js +111 -7
- package/dist/ir/runtime-features.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 +295 -14
- package/dist/ir/validate.js.map +1 -1
- package/dist/ir/validate.test.js +60 -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/cli.js +1 -0
- package/dist/native/cli.js.map +1 -1
- package/dist/native/compiler.js +1 -3
- package/dist/native/compiler.js.map +1 -1
- package/dist/native/prepare.js +4 -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 +1279 -221
|
@@ -1,3 +1,5 @@
|
|
|
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
5
|
import { CYC_BUF, CYC_HDR, FIRST_EMITTED_CYC_KIND, inlineAllocSupported } from "./alloc.js";
|
|
@@ -7,7 +9,7 @@ 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,7 +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";
|
|
19
|
-
import { addRecordResultEntries } from "./record-results.js";
|
|
21
|
+
import { RESULT_ENTRY_PREFIX, addRecordResultEntries } from "./record-results.js";
|
|
20
22
|
import { specializeNumericCalls } from "../../ir/numeric-call-specialization.js";
|
|
21
23
|
import { everyExpr, everyExprChild, everyStmtChild, everyStmtList } from "../../ir/traverse.js";
|
|
22
24
|
import { analyzeIntegerRanges, INT32_RANGE } from "../../ir/integer-ranges.js";
|
|
@@ -40,25 +42,26 @@ import { emitStackObject, findLocalStackObjects, findReassignedStackObjects, sta
|
|
|
40
42
|
import { allocateLocalUnion, emitScalarOptional, findLocalUnionStorage, isScalarOptionalSource, storeLocalUnion, } from "./local-union-storage.js";
|
|
41
43
|
import { BlockBuilder } from "./blocks.js";
|
|
42
44
|
import { NullableRefFields } from "./nullable-fields.js";
|
|
45
|
+
import { InlineUnionFields, loadInlineUnion, presentBits, stackUnionBox, storeInlineUnion, unionBoxBits, } from "./inline-unions.js";
|
|
43
46
|
import { emitLocalArrayRead, emitProjectedArrayRead, emitBorrowedArrayRead, findLocalArrayReads, findCallArrayReads, OptionalArrayReads, } from "./local-array-reads.js";
|
|
44
47
|
import { CheckedNarrows, emitCheckedNarrowReceiver } from "./checked-narrows.js";
|
|
45
48
|
import { emitDenseArrayGet, emitDenseArraySet } from "./dense-array-access.js";
|
|
46
|
-
import { emitStackMapRead, findMapReadLifetimes, matchMapRead, } from "./map-read-lifetimes.js";
|
|
49
|
+
import { emitStackMapRead, findMapReadLifetimes, findReadNumberMapWrites, matchMapRead, } from "./map-read-lifetimes.js";
|
|
47
50
|
import { emitBorrowedFieldSequence, guardedValue } from "./borrowed-receivers.js";
|
|
48
|
-
import { borrowableInputs, emitBorrowedInput } from "./borrowed-inputs.js";
|
|
51
|
+
import { borrowableInputs, emitBorrowedInput, emitBorrowedInputs } from "./borrowed-inputs.js";
|
|
49
52
|
import { analyzeWalks, findWalkBorrows } from "./walk-borrows.js";
|
|
50
53
|
import { findReboundParameters } from "./rebound-parameters.js";
|
|
51
54
|
import { ReferenceEffects } from "./reference-effects.js";
|
|
52
55
|
import { ReferenceWrites } from "./reference-writes.js";
|
|
53
56
|
import { LlvmDebugInfo } from "./debug-info.js";
|
|
54
57
|
import { StackCallbacks } from "./stack-callbacks.js";
|
|
55
|
-
import { findLoopArrayBorrows } from "./loop-array-borrows.js";
|
|
58
|
+
import { dynHoleRead, findLoopArrayBorrows } from "./loop-array-borrows.js";
|
|
56
59
|
import { findAppendedArrayLiterals } from "./appended-array-literals.js";
|
|
57
60
|
import { AmbientReceiverReaders, findConstantCallbacks } from "./constant-callbacks.js";
|
|
58
61
|
import { findScalarStringSlices, emitStringSliceSnapshot, } from "./string-slices.js";
|
|
59
62
|
import { LazyCaptures } from "./lazy-captures.js";
|
|
60
63
|
import { StackCaptures } from "./stack-captures.js";
|
|
61
|
-
import { ABSENT_FIELD_PAYLOAD, emitFieldAbsentTest, exactIndexLines, f64Lit, ffiNativeTypeLl, ffiNativeParamLl, ffiNativeReturnLl, llvmCommentText, } from "./common.js";
|
|
64
|
+
import { ABSENT_FIELD_PAYLOAD, emitFieldAbsentTest, exactIndexLines, f64Lit, ffiNativeTypeLl, ffiNativeParamLl, ffiNativeReturnLl, llvmCommentText, sizeToDouble, } from "./common.js";
|
|
62
65
|
import { ffiExtendsNarrowIntegers } from "../targets.js";
|
|
63
66
|
import { emitLiteralExpr, emitOperatorExpr, emitStringExpr, emitContainerExpr, emitRecordExpr, } from "./expr-primitives.js";
|
|
64
67
|
import { emitControlExpr } from "./expr-control.js";
|
|
@@ -70,7 +73,7 @@ import { computeImmutableFields, stableGlobals } from "../immutability.js";
|
|
|
70
73
|
import { computePublishedTypes } from "../publication.js";
|
|
71
74
|
import { emitExpr } from "./expr-dispatch.js";
|
|
72
75
|
import { dynKind, raceAdapterFor, genResultThunkFor, childExitThunkFor, childExitSignalThunkFor, childDataThunkFor, execFileThunkFor, ipcMessageThunkFor, ipcSendThunkFor, emitterFixedAdapter, wrapEmitterListener, unwrapNullableClosure, closeBindThunkFor, closeOverrideWrapFor, } from "./expr-callbacks.js";
|
|
73
|
-
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";
|
|
74
77
|
import { emitStableReceiver, resolveThunkFor, tagInSet, arrPush, emitArrayCopyLoop, emitStrIntrinsic, emitArrIntrinsic, emitDiscardedSplice, wrapNullable, emitMapNew, mapSet, emitMapLikeIntrinsic, emitSetNew, } from "./expr-containers.js";
|
|
75
78
|
import { emitIntegerLoopIndex, emitBytesIndex, emitBytesData, emitBytesLength, emitBytesGet, emitToUint32, emitBytesSet, emitBytesIntrinsic, } from "./expr-bytes.js";
|
|
76
79
|
import { emitRegexIntrinsic, emitRecordKeyGet, keyedRecordReadInto } from "./expr-records.js";
|
|
@@ -82,17 +85,17 @@ import { emitNetworkHttpLibCall } from "./lib-network.js";
|
|
|
82
85
|
import { emitAssertInspectLibCall, emitIoLibCall, emitGenericLibCall, emitLibCall, } from "./lib-dispatch.js";
|
|
83
86
|
import { buildClassGraph, classMembershipIntervals, emitClassMembershipHelper, classEnvironmentIndex, classFieldIndex, classStructSym, programLifetimeClass, } from "./classes.js";
|
|
84
87
|
import { LifetimeRegions, REGION_TYPES } from "./regions.js";
|
|
85
|
-
import { LlDyn } from "./dyn.js";
|
|
88
|
+
import { LlDyn, recordDynKeepsIdentity } from "./dyn.js";
|
|
86
89
|
import { VirtualBorrows } from "./virtual-borrows.js";
|
|
87
90
|
import { LlvmUnsupportedError } from "./unsupported.js";
|
|
88
91
|
import { LlWalkers } from "./walkers.js";
|
|
89
92
|
import { isObjectArm, NULLABLE_ABSENT, NULLABLE_NULL, NullableUnions } from "./nullable-unions.js";
|
|
90
93
|
import { emitNullablePresent, emitUnionPeek, emitUnionTag } from "./union-repr.js";
|
|
91
94
|
import { literalCapWord, literalCapWord32 } from "./string-key-hash.js";
|
|
92
|
-
import { NUMBER_MAP_ENTRY_DECL, STRING_MAP_ENTRY_DECL } from "./map-number-lookup.js";
|
|
95
|
+
import { MAP_ITER_DECL, NUMBER_MAP_ENTRY_DECL, STRING_MAP_ENTRY_DECL, } from "./map-number-lookup.js";
|
|
93
96
|
import { STRING_READ_HELPERS, stringScanDecl } from "./string-reads.js";
|
|
94
97
|
import { emitConcatInputs, emitMixedConcat, numberPart, stringParts, } from "./string-construction.js";
|
|
95
|
-
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";
|
|
96
99
|
import { INLINE_LITERAL_BYTES, literalEqualityDefinition } from "./string-literal-equality.js";
|
|
97
100
|
export { LlvmUnsupportedError } from "./unsupported.js";
|
|
98
101
|
function ffiCallbackDummyLl(callback) {
|
|
@@ -286,6 +289,8 @@ export class LlEmitter {
|
|
|
286
289
|
unitInstances = new Map();
|
|
287
290
|
/** unionId → symbol of the union's immortal ABSENT field-slot instance. */
|
|
288
291
|
absentInstances = new Map();
|
|
292
|
+
/** The zeroed box an inline store reads for a NULL union dummy. */
|
|
293
|
+
needsUnionNone = false;
|
|
289
294
|
/** unionId → symbol of a flag set once a checked-dynamic cast caches one
|
|
290
295
|
* of the union's boxes. A cached box is refreshed in place, possibly with
|
|
291
296
|
* a tag that another union numbers apart, so it is never shared. */
|
|
@@ -328,6 +333,8 @@ export class LlEmitter {
|
|
|
328
333
|
/** Inline RC fast-path helpers requested by call sites (shapes.ts); null
|
|
329
334
|
* when inline RC is off. */
|
|
330
335
|
rcHelpers;
|
|
336
|
+
rcMode;
|
|
337
|
+
rcHelpersNoinline;
|
|
331
338
|
fnByName = new Map();
|
|
332
339
|
/** Empty literals that construct with inline slots (appended-array-literals.ts). */
|
|
333
340
|
appendedArrayLiterals = new Set();
|
|
@@ -347,6 +354,7 @@ export class LlEmitter {
|
|
|
347
354
|
checkedNarrows;
|
|
348
355
|
callArrayReads = new Map();
|
|
349
356
|
mapReadLifetimes = { locals: new Map(), arguments: new Map() };
|
|
357
|
+
readNumberMapWrites = new Set();
|
|
350
358
|
callLifetimes;
|
|
351
359
|
constantCallbacks;
|
|
352
360
|
currentConstantCallbacks = new Map();
|
|
@@ -439,6 +447,8 @@ export class LlEmitter {
|
|
|
439
447
|
* typeKey → thunk symbol. */
|
|
440
448
|
resolveThunks = new Map();
|
|
441
449
|
resolveThunkDefs = [];
|
|
450
|
+
/** Inline array searches used by the module (array-search.ts). */
|
|
451
|
+
arraySearchKinds = new Set();
|
|
442
452
|
/** Typed-ref recipe constants by type key (lazy receivers). */
|
|
443
453
|
typedRefRecipes = new Map();
|
|
444
454
|
/** ReadableStream.from adapters keep typed arrays by reference and box
|
|
@@ -452,6 +462,7 @@ export class LlEmitter {
|
|
|
452
462
|
dynPromiseAdapters = new Map();
|
|
453
463
|
unionsById = new Map();
|
|
454
464
|
nullableFields;
|
|
465
|
+
inlineUnions;
|
|
455
466
|
/** Unions whose values are nullable arm pointers (nullable-unions.ts). */
|
|
456
467
|
nullableUnions;
|
|
457
468
|
/** The union table without nullable unions: the stack-box analyses. */
|
|
@@ -624,7 +635,9 @@ export class LlEmitter {
|
|
|
624
635
|
this.emitLibraryIdentity = options.emitLibraryIdentity !== false;
|
|
625
636
|
this.runtimeAbiMarker = options.runtimeAbiMarker === true;
|
|
626
637
|
this.detachedExit = options.detachedExit === true;
|
|
627
|
-
this.rcHelpers = options.inlineRc
|
|
638
|
+
this.rcHelpers = options.inlineRc !== undefined ? new Set() : null;
|
|
639
|
+
this.rcMode = options.inlineRc;
|
|
640
|
+
this.rcHelpersNoinline = options.rcHelpersNoinline === true;
|
|
628
641
|
// ScrCycHdr.buf sits 4 bytes behind every object on every target.
|
|
629
642
|
this.cycleBufOffset = CYC_HDR - CYC_BUF;
|
|
630
643
|
this.ffiCallbackAdapters = allocateFfiCallbackAdapters(mod.ffiImports ?? []);
|
|
@@ -662,6 +675,9 @@ export class LlEmitter {
|
|
|
662
675
|
this.immortalValues.add("null");
|
|
663
676
|
this.immortalValues.add(NULLABLE_NULL);
|
|
664
677
|
this.nullableFields = new NullableRefFields(mod.classes ?? [], this.boxedUnionsById);
|
|
678
|
+
this.inlineUnions = new InlineUnionFields(this.boxedUnionsById, mod.classes ?? []);
|
|
679
|
+
for (const r of mod.records ?? [])
|
|
680
|
+
this.recordsById.set(r.id, r);
|
|
665
681
|
// Optional array reads also cover nullable unions: emitLocalArrayRead
|
|
666
682
|
// then yields the (borrowed or owned) element pointer, not a stack box.
|
|
667
683
|
// Arrays of such a union are read the same way.
|
|
@@ -670,6 +686,7 @@ export class LlEmitter {
|
|
|
670
686
|
unions: this.boxedUnionsById,
|
|
671
687
|
receiverUnions: this.unionsById,
|
|
672
688
|
nullableField: (e) => this.nullableFieldGet(e) !== null,
|
|
689
|
+
inlineField: (e) => this.inlineFieldGet(e),
|
|
673
690
|
arrayRead: (e) => this.optionalArrayReads.get(e) !== null,
|
|
674
691
|
scalarCall: (e) => this.scalarResultCall(e),
|
|
675
692
|
};
|
|
@@ -718,14 +735,18 @@ export class LlEmitter {
|
|
|
718
735
|
walkParameters.set(fn.name, indexes);
|
|
719
736
|
}
|
|
720
737
|
}
|
|
721
|
-
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
|
+
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)), {
|
|
739
|
+
record: (shapeId, field) => this.recordFieldInline(shapeId, field),
|
|
740
|
+
classField: (className, field) => this.inlineUnions.classField(className, field),
|
|
741
|
+
}, (shapeId) => {
|
|
742
|
+
const shape = this.recordsById.get(shapeId);
|
|
743
|
+
return shape !== undefined && !recordDynKeepsIdentity(shape);
|
|
744
|
+
});
|
|
722
745
|
this.constantCallbacks = findConstantCallbacks(mod, this.callLifetimes);
|
|
723
746
|
this.stackCallbacks = new StackCallbacks(this.fnByName);
|
|
724
747
|
this.receiverReaders = new AmbientReceiverReaders(this.fnByName);
|
|
725
748
|
this.stackCaptures = new StackCaptures(this.fnByName, this.callLifetimes, this.stackCallbacks);
|
|
726
749
|
this.lazyCaptures = new LazyCaptures(this.fnByName);
|
|
727
|
-
for (const r of mod.records ?? [])
|
|
728
|
-
this.recordsById.set(r.id, r);
|
|
729
750
|
const traced = computeTraced(mod);
|
|
730
751
|
this.tracedShapes = traced.shapes;
|
|
731
752
|
this.tracedUnions = traced.unions;
|
|
@@ -735,6 +756,8 @@ export class LlEmitter {
|
|
|
735
756
|
tracedShapes: this.tracedShapes,
|
|
736
757
|
tracedUnions: this.tracedUnions,
|
|
737
758
|
nullableUnions: this.nullableUnions,
|
|
759
|
+
inlineUnions: this.inlineUnions,
|
|
760
|
+
unionNoneRef: () => this.unionNoneRef(),
|
|
738
761
|
recordsById: this.recordsById,
|
|
739
762
|
recordCloneShapes: this.recordCloneShapes,
|
|
740
763
|
objectAudit: options.objectAudit !== false,
|
|
@@ -748,6 +771,8 @@ export class LlEmitter {
|
|
|
748
771
|
// paths address its thread-local state.
|
|
749
772
|
threadLocalAlloc: mod.workers === true,
|
|
750
773
|
rcHelpers: this.rcHelpers,
|
|
774
|
+
...(this.rcMode !== undefined ? { rcMode: this.rcMode } : {}),
|
|
775
|
+
...(this.rcHelpersNoinline ? { rcHelpersNoinline: true } : {}),
|
|
751
776
|
nextCycKind: () => FIRST_EMITTED_CYC_KIND + this.cycKinds++,
|
|
752
777
|
unionsById: this.unionsById,
|
|
753
778
|
declare: (decl) => this.declare(decl),
|
|
@@ -763,6 +788,7 @@ export class LlEmitter {
|
|
|
763
788
|
liveDynUnionRefAdapter: (type) => this.liveDynUnionRefAdapter(type),
|
|
764
789
|
dynPromiseAdapter: (type) => this.dynPromiseAdapter(type),
|
|
765
790
|
isErrorClass: (name) => this.classMeta.get(name)?.root.def.name === "%Error",
|
|
791
|
+
classRootOf: (name) => this.classMeta.get(name)?.root.def.name,
|
|
766
792
|
classSubtypes: (name) => {
|
|
767
793
|
const target = this.classMetaOf(name);
|
|
768
794
|
const intervals = classMembershipIntervals(this.classMeta, target.def.name);
|
|
@@ -796,13 +822,16 @@ export class LlEmitter {
|
|
|
796
822
|
this.tdzGlobals.set(g.id, g.name);
|
|
797
823
|
}
|
|
798
824
|
this.stableGlobals = stableGlobals(mod);
|
|
799
|
-
// Runtime error, EventEmitter,
|
|
800
|
-
// Subclasses embed the
|
|
825
|
+
// Runtime error, EventEmitter, stream, EventTarget and Event classes
|
|
826
|
+
// have known layouts. Subclasses embed the runtime prefixes from
|
|
827
|
+
// classes.ts.
|
|
801
828
|
const classes = mod.classes ?? [];
|
|
802
829
|
for (const cls of classes) {
|
|
803
830
|
if (cls.runtime &&
|
|
804
831
|
!RUNTIME_ERROR_CLASSES.has(cls.name) &&
|
|
805
832
|
cls.name !== RUNTIME_EMITTER_CLASS &&
|
|
833
|
+
cls.name !== RUNTIME_EVENT_TARGET_CLASS &&
|
|
834
|
+
cls.name !== RUNTIME_EVENT_CLASS &&
|
|
806
835
|
!RUNTIME_STREAM_CLASSES.has(cls.name)) {
|
|
807
836
|
throw new LlvmUnsupportedError(`classDef:${cls.name}`, cls.loc);
|
|
808
837
|
}
|
|
@@ -1162,7 +1191,7 @@ export class LlEmitter {
|
|
|
1162
1191
|
return this.emitParts().join("\n");
|
|
1163
1192
|
}
|
|
1164
1193
|
emitParts() {
|
|
1165
|
-
const parts = this.emitModuleParts();
|
|
1194
|
+
const parts = limitInlineDynReleases(this.emitModuleParts());
|
|
1166
1195
|
if (!this.executableTls)
|
|
1167
1196
|
return parts;
|
|
1168
1197
|
// A worker executable's thread-locals all live in the executable's own
|
|
@@ -1215,7 +1244,7 @@ export class LlEmitter {
|
|
|
1215
1244
|
// Module globals, FIRST OCCURRENCE per id: a class-expression static
|
|
1216
1245
|
// instantiated through several mixin applications registers one global
|
|
1217
1246
|
// id several times (2041-mixin-values) — C's tentative definitions
|
|
1218
|
-
//
|
|
1247
|
+
// accept the duplicates without an error, LLVM rejects redefinition, so the
|
|
1219
1248
|
// storage AND the release emit once per id here.
|
|
1220
1249
|
const seenGlobalIds = new Set();
|
|
1221
1250
|
const globals = (this.mod.globals ?? []).filter((g) => {
|
|
@@ -1388,21 +1417,17 @@ export class LlEmitter {
|
|
|
1388
1417
|
if (!asyncEntry)
|
|
1389
1418
|
return [];
|
|
1390
1419
|
const lines = [];
|
|
1420
|
+
// finish_top_level noted 13 unless the program set process.exitCode.
|
|
1421
|
+
// A failed node:test run outranks either before exit listeners run.
|
|
1391
1422
|
if (usesNodeTest) {
|
|
1392
|
-
lines.push(` %tla_program_exit = call i32 @scr_test_exit_code()`);
|
|
1423
|
+
lines.push(` %tla_program_exit = call i32 @scr_test_exit_code()`, ` %tla_program_exit_zero = icmp eq i32 %tla_program_exit, 0`, ` %tla_hint = call i32 @scr_exit_code_hint_get()`, ` %tla_exit_status = select i1 %tla_program_exit_zero, i32 %tla_hint, i32 %tla_program_exit`, ` call void @scr_exit_code_note(i32 %tla_exit_status)`);
|
|
1393
1424
|
}
|
|
1394
|
-
if (usesNodeTest) {
|
|
1395
|
-
lines.push(` %tla_program_exit_zero = icmp eq i32 %tla_program_exit, 0`, ` %tla_exit_status = select i1 %tla_program_exit_zero, i32 %tla_status, i32 %tla_program_exit`);
|
|
1396
|
-
}
|
|
1397
|
-
const exitStatus = usesNodeTest ? "%tla_exit_status" : "%tla_status";
|
|
1398
|
-
// finish_top_level initially notes 13. Replace that hint before exit
|
|
1399
|
-
// listeners run when a higher-priority verdict was already selected.
|
|
1400
|
-
lines.push(` call void @scr_exit_code_note(i32 ${exitStatus})`);
|
|
1401
1425
|
for (const line of exitListenerLines("xp"))
|
|
1402
1426
|
lines.push(line);
|
|
1403
1427
|
for (const line of topPendingReleases)
|
|
1404
1428
|
lines.push(line);
|
|
1405
|
-
|
|
1429
|
+
// An exit listener may set process.exitCode again, as in Node.
|
|
1430
|
+
lines.push(` %tla_exit_code = call i32 @scr_exit_code_hint_get()`, ` ret i32 %tla_exit_code`);
|
|
1406
1431
|
return lines;
|
|
1407
1432
|
};
|
|
1408
1433
|
// LIBRARY mode: the runtime entry points the generated library
|
|
@@ -1451,6 +1476,7 @@ export class LlEmitter {
|
|
|
1451
1476
|
// write/abort declarations).
|
|
1452
1477
|
const helpers = [
|
|
1453
1478
|
...this.helperDefs(),
|
|
1479
|
+
...emitArraySearchHelpers(this.arraySearchKinds, this.sizeType, (line) => this.declare(line)),
|
|
1454
1480
|
...emitClassMembershipHelper(this.classMeta, this.sizeType),
|
|
1455
1481
|
...(this.publishWalkersCache?.defs() ?? []),
|
|
1456
1482
|
...this.publishedClassNamesDefs(),
|
|
@@ -1500,17 +1526,22 @@ export class LlEmitter {
|
|
|
1500
1526
|
? []
|
|
1501
1527
|
: [`%ScrMapRc = type { ${this.sizeType}, i32, i32, ptr, ptr, ptr, ptr, ptr, ptr }`]),
|
|
1502
1528
|
// The complete ScrMap and its { key, val, hash } entry, read by the
|
|
1503
|
-
// inline number-key lookup (sc_map_entry_f64)
|
|
1504
|
-
//
|
|
1505
|
-
//
|
|
1506
|
-
|
|
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)
|
|
1507
1536
|
? [
|
|
1508
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} }`,
|
|
1509
1538
|
]
|
|
1510
1539
|
: []),
|
|
1511
1540
|
// String-keyed reference reads load the value slot of the entry
|
|
1512
1541
|
// scr_map_entry_str returns (map-number-lookup.ts).
|
|
1513
|
-
...(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)
|
|
1514
1545
|
? [`%ScrMapEntry = type { i64, i64, i64 }`]
|
|
1515
1546
|
: []),
|
|
1516
1547
|
// The runtime error prefix { rc, vt, name, message, code, cause } and the
|
|
@@ -1524,6 +1555,13 @@ export class LlEmitter {
|
|
|
1524
1555
|
// The runtime stream layout { rc, vt, reg, cls, st } — one struct
|
|
1525
1556
|
// for all five stream classes; stream subclasses embed it.
|
|
1526
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
|
+
: []),
|
|
1527
1565
|
// The catch-binding snapshot box { rc, kind, f64, b, payload,
|
|
1528
1566
|
// retain_fn, release_fn, trace_fn } — caughtTest kind reads and
|
|
1529
1567
|
// caughtNarrow payload extraction GEP through it (offsets match
|
|
@@ -1636,6 +1674,8 @@ export class LlEmitter {
|
|
|
1636
1674
|
}
|
|
1637
1675
|
if (this.absentInstances.size > 0)
|
|
1638
1676
|
out.push(``);
|
|
1677
|
+
if (this.needsUnionNone)
|
|
1678
|
+
out.push(`@sc_union_none = internal constant %ScrUnion zeroinitializer ; NULL union dummy read by inline stores`, ``);
|
|
1639
1679
|
if (this.nullableUnions.usesNullSentinel) {
|
|
1640
1680
|
// `null` in every `C | null | undefined` union (NULL is undefined):
|
|
1641
1681
|
// one module-scope immortal object like the ABSENT sentinel.
|
|
@@ -2050,7 +2090,7 @@ export class LlEmitter {
|
|
|
2050
2090
|
case "i64":
|
|
2051
2091
|
// Inbound declared-integer edge (ask 4): the helper converts
|
|
2052
2092
|
// exactly or delivers the host-contract trap (past ±(2^53−1)
|
|
2053
|
-
// the value cannot ride f64 without
|
|
2093
|
+
// the value cannot ride f64 without rounding).
|
|
2054
2094
|
params.push(`i64 %a${i}`);
|
|
2055
2095
|
body.push(` %c${i} = call double @scr_library_i64_in(i64 %a${i}, ptr @sc_lib_int_trap_${e.symbol})`);
|
|
2056
2096
|
args.push(`double %c${i}`);
|
|
@@ -2145,9 +2185,13 @@ export class LlEmitter {
|
|
|
2145
2185
|
// Number-key Map/Set lookups probe the runtime's direct index inline:
|
|
2146
2186
|
// while ndense is nonzero every live key is an integer below it, so an
|
|
2147
2187
|
// in-range integral key reads its slot (entry index + 1, 0 = absent) and
|
|
2148
|
-
// any other key is absent. Maps without the index (ndense 0)
|
|
2149
|
-
//
|
|
2150
|
-
//
|
|
2188
|
+
// any other key is absent. Maps without the index (ndense 0) hash the
|
|
2189
|
+
// key in sc_map_entry_f64_hashed, which scans the entries of a small map
|
|
2190
|
+
// or probes a compact bucket table as scr_map_find_f64 does, and calls
|
|
2191
|
+
// the runtime lookup for a wide table. It stays out of line so that the
|
|
2192
|
+
// direct-index path stays small at every call site. Both only read
|
|
2193
|
+
// memory, so LLVM merges lookups of one key when nothing is stored in
|
|
2194
|
+
// between (a has() followed by get(), for example).
|
|
2151
2195
|
if (this.decls.has(NUMBER_MAP_ENTRY_DECL)) {
|
|
2152
2196
|
const sz = this.sizeType;
|
|
2153
2197
|
let mapTmp = 0;
|
|
@@ -2156,7 +2200,24 @@ export class LlEmitter {
|
|
|
2156
2200
|
// A non-integral key inside the table is as absent as one outside it.
|
|
2157
2201
|
...mapIndex.lines.map((line) => ` ${line}`), ` br i1 ${mapIndex.ok}, label %slot, label %outside`, `slot:`, sz === "i64"
|
|
2158
2202
|
? ` %i = add i64 ${mapIndex.wide}, 0`
|
|
2159
|
-
: ` %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:`, ` %
|
|
2203
|
+
: ` %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:`, ` %hashed = call ptr @sc_map_entry_f64_hashed(ptr %m, double %k)`, ` ret ptr %hashed`, `}`, ``,
|
|
2204
|
+
// Hashing (scr_map_find_f64): the SameValueZero key word, its
|
|
2205
|
+
// scr_key_mix hash (zero remapped to one) and the absent-key filter.
|
|
2206
|
+
`define internal ptr @sc_map_entry_f64_hashed(ptr %m, double %k) noinline ${FN_ATTRS} {`, `entry:`, ` %nan = fcmp uno double %k, %k`, ` %zero = fcmp oeq double %k, 0.0`, ` %kz = select i1 %zero, double 0.0, double %k`, ` %kzb = bitcast double %kz to i64`, ` %kb = select i1 %nan, i64 9221120237041090560, i64 %kzb`, ` %x1s = lshr i64 %kb, 30`, ` %x1 = xor i64 %kb, %x1s`, ` %x2 = mul i64 %x1, -4658895280553007687`, ` %x3s = lshr i64 %x2, 27`, ` %x3 = xor i64 %x2, %x3s`, ` %x4 = mul i64 %x3, -7723592293110705685`, ` %x5s = lshr i64 %x4, 31`, ` %x5 = xor i64 %x4, %x5s`, ` %hz = icmp eq i64 %x5, 0`, ` %h = select i1 %hz, i64 1, i64 %x5`, ` %f1s = lshr i64 %h, 44`, ` %f1a = and i64 %f1s, 63`, ` %f1 = shl i64 1, %f1a`, ` %f2s = lshr i64 %h, 50`, ` %f2a = and i64 %f2s, 63`, ` %f2 = shl i64 1, %f2a`, ` %fb = or i64 %f1, %f2`, ` %fp = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 11`, ` %filter = load i64, ptr %fp`, ` %fm = and i64 %filter, %fb`, ` %fin = icmp eq i64 %fm, %fb`, ` br i1 %fin, label %table, label %miss`, `table:`, ` %nbp = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 14`, ` %nb = load ${sz}, ptr %nbp`, ` %eps = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 13`, ` %ents = load ptr, ptr %eps`, ` %linear = icmp eq ${sz} %nb, 0`, ` br i1 %linear, label %scan, label %buckets`,
|
|
2207
|
+
// Small maps keep no bucket table: scan the cached entry hashes.
|
|
2208
|
+
`scan:`, ` %nep = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 9`, ` %ne = load ${sz}, ptr %nep`, ` br label %scan.loop`, `scan.loop:`, ` %si = phi ${sz} [ 0, %scan ], [ %si.next, %scan.next ]`, ` %sdone = icmp eq ${sz} %si, %ne`, ` br i1 %sdone, label %miss, label %scan.entry`, `scan.entry:`, ` %se = getelementptr inbounds %ScrMapEntry, ptr %ents, ${sz} %si`, ` %seh = getelementptr inbounds %ScrMapEntry, ptr %se, i32 0, i32 2`, ` %sh = load i64, ptr %seh`, ` %sk = load i64, ptr %se`, ` %shq = icmp eq i64 %sh, %h`, ` %skq = icmp eq i64 %sk, %kb`, ` %sq = and i1 %shq, %skq`, ` br i1 %sq, label %scan.found, label %scan.next`, `scan.found:`, ` ret ptr %se`, `scan.next:`, ` %si.next = add ${sz} %si, 1`, ` br label %scan.loop`,
|
|
2209
|
+
// Compact tables tag each 24-bit entry index (+1) with the hash's
|
|
2210
|
+
// top byte; wider tables take the runtime lookup.
|
|
2211
|
+
`buckets:`, ` %wide = icmp ugt ${sz} %nb, 16777216`, ` br i1 %wide, label %runtime, label %probe`, `probe:`, ` %bp = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 15`, ` %bk = load ptr, ptr %bp`, ` %mask = sub ${sz} %nb, 1`, ` %ht = lshr i64 %h, 32`, ` %ht32 = trunc i64 %ht to i32`, ` %tag = and i32 %ht32, -16777216`, sz === "i64" ? ` %hi = add i64 %h, 0` : ` %hi = trunc i64 %h to ${sz}`, ` %i0 = and ${sz} %hi, %mask`, ` br label %probe.loop`, `probe.loop:`, ` %pi = phi ${sz} [ %i0, %probe ], [ %pi.next, %probe.next ]`, ` %bep = getelementptr inbounds i32, ptr %bk, ${sz} %pi`, ` %b = load i32, ptr %bep`, ` %bempty = icmp eq i32 %b, 0`, ` br i1 %bempty, label %miss, label %probe.tag`, `probe.tag:`, ` %bt = and i32 %b, -16777216`, ` %btq = icmp eq i32 %bt, %tag`, ` br i1 %btq, label %probe.entry, label %probe.next`, `probe.entry:`, ` %bix = and i32 %b, 16777215`, ` %bix1 = sub i32 %bix, 1`, sz === "i32" ? ` %bi = add i32 %bix1, 0` : ` %bi = zext i32 %bix1 to ${sz}`, ` %pe = getelementptr inbounds %ScrMapEntry, ptr %ents, ${sz} %bi`, ` %peh = getelementptr inbounds %ScrMapEntry, ptr %pe, i32 0, i32 2`, ` %ph = load i64, ptr %peh`, ` %pk = load i64, ptr %pe`, ` %phq = icmp eq i64 %ph, %h`, ` %pkq = icmp eq i64 %pk, %kb`, ` %pq = and i1 %phq, %pkq`, ` br i1 %pq, label %probe.found, label %probe.next`, `probe.found:`, ` ret ptr %pe`, `probe.next:`, ` %pi.inc = add ${sz} %pi, 1`, ` %pi.next = and ${sz} %pi.inc, %mask`, ` br label %probe.loop`, `miss:`, ` ret ptr null`, `runtime:`, ` %r = call ptr @scr_map_entry_f64(ptr %m, double %k) memory(read) nounwind willreturn`, ` ret ptr %r`, `}`, ``);
|
|
2212
|
+
}
|
|
2213
|
+
// Map/Set iteration steps read the entries array inline: an index is
|
|
2214
|
+
// live when it is below the entry count and its entry's cached hash is
|
|
2215
|
+
// nonzero (a tombstone's is zero), as scr_map_iter_live decides. The
|
|
2216
|
+
// entry count is read again at every step, so entries appended during
|
|
2217
|
+
// the iteration are visited.
|
|
2218
|
+
if (this.decls.has(MAP_ITER_DECL)) {
|
|
2219
|
+
const sz = this.sizeType;
|
|
2220
|
+
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`, `}`, ``);
|
|
2160
2221
|
}
|
|
2161
2222
|
// String-key Map/Set lookups test the map's absent-key filter inline
|
|
2162
2223
|
// (scr_map.c scr_map_filter_bits): a key whose two filter bits are not
|
|
@@ -2398,7 +2459,7 @@ export class LlEmitter {
|
|
|
2398
2459
|
* programs keep fibers too: their fiber epilogue owns context
|
|
2399
2460
|
* termination (a stopping worker rejects and observes the promise), which
|
|
2400
2461
|
* the fiberless wrapper does not reproduce. A missed suspension still
|
|
2401
|
-
* cannot reorder
|
|
2462
|
+
* cannot reorder execution undetected: the runtime traps when a context parks while a
|
|
2402
2463
|
* fiberless body is on its stack. */
|
|
2403
2464
|
fiberlessAsyncFunctions() {
|
|
2404
2465
|
const eligible = new Set();
|
|
@@ -3050,8 +3111,13 @@ export class LlEmitter {
|
|
|
3050
3111
|
* holding the ABSENT state surfaces as the ordinary undefined arm, so
|
|
3051
3112
|
* absence never travels beyond its slot (a later `{ f: r.f }` is an
|
|
3052
3113
|
* explicit, present property). */
|
|
3053
|
-
loadRecordField(ptr, t) {
|
|
3054
|
-
|
|
3114
|
+
loadRecordField(ptr, t, inline) {
|
|
3115
|
+
if (inline) {
|
|
3116
|
+
const { tag, bits } = loadInlineUnion(this.B, ptr);
|
|
3117
|
+
const present = presentBits(this.B, tag, bits, undefinedArmTag(t, this.unionsById));
|
|
3118
|
+
return stackUnionBox(this.B, this.sizeType, tag, present);
|
|
3119
|
+
}
|
|
3120
|
+
const v = this.loadField(ptr, t, false);
|
|
3055
3121
|
if (t.kind !== "union" || undefinedArmTag(t, this.unionsById) < 0)
|
|
3056
3122
|
return v;
|
|
3057
3123
|
const absent = this.fieldAbsentTest(v, t.unionId);
|
|
@@ -3550,6 +3616,11 @@ export class LlEmitter {
|
|
|
3550
3616
|
this.B.line(`store i32 0, ptr ${slot}`);
|
|
3551
3617
|
return slot;
|
|
3552
3618
|
}
|
|
3619
|
+
/** The amortized cancellation poll, emitted on the loop's back edge (the
|
|
3620
|
+
* continue target), after the body. A poll in the header would be a loop
|
|
3621
|
+
* exit ahead of the body; LLVM then cannot rotate the loop, so loads that
|
|
3622
|
+
* the body repeats on every iteration (a typed array's length, for one)
|
|
3623
|
+
* stay in the loop. */
|
|
3553
3624
|
emitWorkerLoopCheck(slot) {
|
|
3554
3625
|
if (slot === null)
|
|
3555
3626
|
return;
|
|
@@ -3713,6 +3784,7 @@ export class LlEmitter {
|
|
|
3713
3784
|
case "searchParams":
|
|
3714
3785
|
case "stats":
|
|
3715
3786
|
case "fileHandle":
|
|
3787
|
+
case "dir":
|
|
3716
3788
|
case "spawnRes":
|
|
3717
3789
|
case "child":
|
|
3718
3790
|
case "childStream":
|
|
@@ -3755,7 +3827,7 @@ export class LlEmitter {
|
|
|
3755
3827
|
}
|
|
3756
3828
|
/** Guard for helpers that build or read a union's `%ScrUnion` box
|
|
3757
3829
|
* directly (library-shaped unions with fixed arms): a nullable union
|
|
3758
|
-
* reaching one is an emitter bug
|
|
3830
|
+
* reaching one is an emitter bug and throws InternalCompilerError. */
|
|
3759
3831
|
requireBoxedUnion(unionId) {
|
|
3760
3832
|
if (this.nullableUnions.has(unionId))
|
|
3761
3833
|
throw new InternalCompilerError(`llvm emitter bug: nullable union ${unionId} reached a tagged-box helper`);
|
|
@@ -3888,7 +3960,7 @@ export class LlEmitter {
|
|
|
3888
3960
|
const p = this.B.tmp();
|
|
3889
3961
|
this.B.line(`${p} = getelementptr inbounds %${classStructSym(className)}, ptr ${objName}, i64 0, i32 ${index}`);
|
|
3890
3962
|
this.markFieldPointer(p, field);
|
|
3891
|
-
return { ptr: p, type };
|
|
3963
|
+
return { ptr: p, type, inline: this.inlineUnions.classField(className, field) };
|
|
3892
3964
|
}
|
|
3893
3965
|
/** `o->vt->pre` — the dynamic class's preorder number (borrowed object;
|
|
3894
3966
|
* the static class names which struct spelling carries the vt word). */
|
|
@@ -3939,8 +4011,10 @@ export class LlEmitter {
|
|
|
3939
4011
|
if (index < 0)
|
|
3940
4012
|
throw new InternalCompilerError(`llvm emitter bug: missing union field ${field}`);
|
|
3941
4013
|
layout = "record:";
|
|
3942
|
-
for (let i = 0; i <= index; i++)
|
|
3943
|
-
|
|
4014
|
+
for (let i = 0; i <= index; i++) {
|
|
4015
|
+
const type = shape.fields[i].type;
|
|
4016
|
+
layout += `${llFieldType(type, this.inlineUnions.record(type))};`;
|
|
4017
|
+
}
|
|
3944
4018
|
}
|
|
3945
4019
|
const group = groups.get(layout);
|
|
3946
4020
|
if (group)
|
|
@@ -3952,7 +4026,13 @@ export class LlEmitter {
|
|
|
3952
4026
|
this.unionFieldReadGroups.set(key, result);
|
|
3953
4027
|
return result;
|
|
3954
4028
|
}
|
|
3955
|
-
/** The
|
|
4029
|
+
/** The zeroed `%ScrUnion` constant (inline-unions.ts unionBoxBits). */
|
|
4030
|
+
unionNoneRef() {
|
|
4031
|
+
this.needsUnionNone = true;
|
|
4032
|
+
return "@sc_union_none";
|
|
4033
|
+
}
|
|
4034
|
+
/** The field-slot pointer of a record member (rc header at index 0).
|
|
4035
|
+
* `inline`: the slot stores a scalar union's tag and bits. */
|
|
3956
4036
|
recordFieldPtr(objName, shapeId, field) {
|
|
3957
4037
|
const shape = this.recordShape(shapeId);
|
|
3958
4038
|
const idx = shape.fields.findIndex((f) => f.name === field);
|
|
@@ -3960,7 +4040,8 @@ export class LlEmitter {
|
|
|
3960
4040
|
throw new InternalCompilerError(`llvm emitter bug: unknown field ${field} on shape ${shapeId}`);
|
|
3961
4041
|
const p = this.B.tmp();
|
|
3962
4042
|
this.B.line(`${p} = getelementptr inbounds %${mangleRecordStruct(shapeId)}, ptr ${objName}, i64 0, i32 ${idx + 1}`);
|
|
3963
|
-
|
|
4043
|
+
const type = shape.fields[idx].type;
|
|
4044
|
+
return { ptr: p, type, inline: this.inlineUnions.record(type) };
|
|
3964
4045
|
}
|
|
3965
4046
|
/** The overflow map's slot pointer on an index-signature shape. */
|
|
3966
4047
|
recordOvfPtr(objName, shapeId) {
|
|
@@ -3973,10 +4054,16 @@ export class LlEmitter {
|
|
|
3973
4054
|
this.B.line(`${v} = load ptr, ptr ${p}`);
|
|
3974
4055
|
return v;
|
|
3975
4056
|
}
|
|
3976
|
-
/** Loads a record field (i8-stored bools trunc to i1).
|
|
3977
|
-
|
|
4057
|
+
/** Loads a record field (i8-stored bools trunc to i1). An inline union
|
|
4058
|
+
* field answers a private stack box with the slot's own bits, ABSENT
|
|
4059
|
+
* included: it may only be borrowed. */
|
|
4060
|
+
loadField(ptr, t, inline) {
|
|
3978
4061
|
const B = this.B;
|
|
3979
|
-
|
|
4062
|
+
if (inline) {
|
|
4063
|
+
const { tag, bits } = loadInlineUnion(B, ptr);
|
|
4064
|
+
return stackUnionBox(B, this.sizeType, tag, bits);
|
|
4065
|
+
}
|
|
4066
|
+
const fieldTy = llFieldType(t, false);
|
|
3980
4067
|
const raw = B.tmp();
|
|
3981
4068
|
B.line(`${raw} = load ${fieldTy}, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
3982
4069
|
if (fieldTy !== "i8")
|
|
@@ -3985,10 +4072,46 @@ export class LlEmitter {
|
|
|
3985
4072
|
B.line(`${b} = trunc i8 ${raw} to i1`);
|
|
3986
4073
|
return b;
|
|
3987
4074
|
}
|
|
3988
|
-
/**
|
|
3989
|
-
|
|
4075
|
+
/** A record field of this shape stores its scalar union inline. */
|
|
4076
|
+
recordFieldInline(shapeId, field) {
|
|
4077
|
+
const type = this.recordShape(shapeId).fields.find((f) => f.name === field)?.type;
|
|
4078
|
+
return type !== undefined && this.inlineUnions.record(type);
|
|
4079
|
+
}
|
|
4080
|
+
/** The value a field store writes: an inline union slot copies the tag
|
|
4081
|
+
* and bits of a borrowed projection, so no box is built for it. */
|
|
4082
|
+
emitFieldValue(value, inline) {
|
|
4083
|
+
return inline ? this.emitUnionProjection(value) : this.emitExpr(value);
|
|
4084
|
+
}
|
|
4085
|
+
/** Overwrites a field with `v` (from emitFieldValue). A reference moves
|
|
4086
|
+
* in, and the old value is released AFTER the field is overwritten. */
|
|
4087
|
+
replaceField(ptr, type, inline, v) {
|
|
4088
|
+
if (!inline && isRefCounted(type)) {
|
|
4089
|
+
this.moveTemp(v);
|
|
4090
|
+
const old = this.B.tmp();
|
|
4091
|
+
this.B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
4092
|
+
this.storeField(ptr, type, v.name, false);
|
|
4093
|
+
this.releaseValue(old, type);
|
|
4094
|
+
return;
|
|
4095
|
+
}
|
|
4096
|
+
this.storeField(ptr, type, v.name, inline);
|
|
4097
|
+
}
|
|
4098
|
+
/** Stores `v` (from emitFieldValue) into a fresh field slot. */
|
|
4099
|
+
initField(ptr, type, inline, v) {
|
|
4100
|
+
if (!inline && isRefCounted(type))
|
|
4101
|
+
this.moveTemp(v);
|
|
4102
|
+
this.storeField(ptr, type, v.name, inline);
|
|
4103
|
+
}
|
|
4104
|
+
/** Stores a record field (i1 zext to the i8 storage). An inline union
|
|
4105
|
+
* field copies the tag and bits of the union value, which its owner
|
|
4106
|
+
* keeps. */
|
|
4107
|
+
storeField(ptr, t, value, inline) {
|
|
3990
4108
|
const B = this.B;
|
|
3991
|
-
|
|
4109
|
+
if (inline) {
|
|
4110
|
+
const { tag, bits } = unionBoxBits(B, value, this.unionNoneRef());
|
|
4111
|
+
storeInlineUnion(B, ptr, tag, bits);
|
|
4112
|
+
return;
|
|
4113
|
+
}
|
|
4114
|
+
const fieldTy = llFieldType(t, false);
|
|
3992
4115
|
if (fieldTy !== "i8") {
|
|
3993
4116
|
B.line(`store ${fieldTy} ${value}, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
3994
4117
|
return;
|
|
@@ -4458,13 +4581,14 @@ export class LlEmitter {
|
|
|
4458
4581
|
this.integerArrayBindings.clear();
|
|
4459
4582
|
this.loopArrayBorrows =
|
|
4460
4583
|
this.debug === null
|
|
4461
|
-
? findLoopArrayBorrows(fn, this.callLifetimes, this.referenceEffects, this.optionalArrayReads, this.referenceWrites)
|
|
4584
|
+
? findLoopArrayBorrows(fn, this.callLifetimes, this.referenceEffects, this.optionalArrayReads, this.referenceWrites, this.fnByName)
|
|
4462
4585
|
: new Set();
|
|
4463
4586
|
this.localArrayReads = findLocalArrayReads(fn, this.fnByName, this.unionsById, this.referenceEffects.functions, this.callLifetimes, this.optionalArrayReads, this.loopArrayBorrows, this.debug === null ? this.referenceEffects : undefined);
|
|
4464
4587
|
this.callArrayReads = findCallArrayReads(fn, this.optionalArrayReads, this.referenceEffects.functions, this.callLifetimes, this.debug === null ? this.referenceEffects : undefined);
|
|
4465
4588
|
this.scalarStringSlices =
|
|
4466
4589
|
this.debug === null ? findScalarStringSlices(fn, this.callLifetimes) : new Map();
|
|
4467
4590
|
this.mapReadLifetimes = findMapReadLifetimes(fn, this.boxedUnionsById, this.callLifetimes);
|
|
4591
|
+
this.readNumberMapWrites = findReadNumberMapWrites(fn);
|
|
4468
4592
|
this.localStackUnions = findLocalStackUnions(fn, this.callLifetimes, this.boxedUnionsById);
|
|
4469
4593
|
this.localStackObjects = this.stackObjects
|
|
4470
4594
|
? findLocalStackObjects(this, fn, this.callLifetimes)
|
|
@@ -4775,6 +4899,15 @@ export class LlEmitter {
|
|
|
4775
4899
|
// a call, and an integer index converts to a double and back across it.
|
|
4776
4900
|
if (fn.name.startsWith("%arr.idxOr."))
|
|
4777
4901
|
attrs = `inlinehint ${attrs}`;
|
|
4902
|
+
// Interface dispatch is a few key tests and direct calls ahead of the
|
|
4903
|
+
// checked dynamic call. Keeping that fallback out of line leaves the
|
|
4904
|
+
// tests small enough to inline at each call site.
|
|
4905
|
+
if (fn.name.startsWith("%dyn.class.protocol.fallback."))
|
|
4906
|
+
attrs = `noinline ${attrs}`;
|
|
4907
|
+
else if (fn.name.startsWith("%dyn.class.protocol."))
|
|
4908
|
+
attrs = `inlinehint ${attrs}`;
|
|
4909
|
+
if (fn.name.startsWith(RESULT_ENTRY_PREFIX))
|
|
4910
|
+
attrs = `inlinehint ${attrs}`;
|
|
4778
4911
|
const debug = this.debugScope === null ? "" : ` !dbg ${this.debugScope}`;
|
|
4779
4912
|
const symbol = borrowed ? mangleBorrowedFunction(fn.name) : mangleFunction(fn.name);
|
|
4780
4913
|
let body = `define internal ${ret} @${symbol}${int32Abi ? INT32_ABI_SUFFIX : ""}(${params.join(", ")}) ${attrs}${debug} { ; ${fn.name}\n${B.render()}\n}`;
|
|
@@ -4861,11 +4994,23 @@ export class LlEmitter {
|
|
|
4861
4994
|
* exception dummy (tag -1) answers NULL. */
|
|
4862
4995
|
boxScalarUnion(pair, type) {
|
|
4863
4996
|
const B = this.B;
|
|
4864
|
-
const unionId = type.kind === "union" ? type.unionId : "";
|
|
4865
|
-
const arms = this.unionsById.get(unionId).arms;
|
|
4866
4997
|
const tag = B.tmp(), bits = B.tmp();
|
|
4867
4998
|
B.line(`${tag} = extractvalue ${SCALAR_UNION_RESULT} ${pair}, 0`);
|
|
4868
4999
|
B.line(`${bits} = extractvalue ${SCALAR_UNION_RESULT} ${pair}, 1`);
|
|
5000
|
+
return this.boxScalarUnionBits(tag, bits, type);
|
|
5001
|
+
}
|
|
5002
|
+
/** A fresh heap box (+1) for an inline union field's value; the ABSENT
|
|
5003
|
+
* state reads as the undefined arm. */
|
|
5004
|
+
inlineFieldUnion(ptr, type) {
|
|
5005
|
+
const { tag, bits } = loadInlineUnion(this.B, ptr);
|
|
5006
|
+
return this.boxScalarUnionBits(tag, bits, type);
|
|
5007
|
+
}
|
|
5008
|
+
/** boxScalarUnion over a separate tag and payload bits. Unit arms answer
|
|
5009
|
+
* their immortal instances whatever the bits. */
|
|
5010
|
+
boxScalarUnionBits(tag, bits, type) {
|
|
5011
|
+
const B = this.B;
|
|
5012
|
+
const unionId = type.kind === "union" ? type.unionId : "";
|
|
5013
|
+
const arms = this.unionsById.get(unionId).arms;
|
|
4869
5014
|
const join = B.newLabel("union.box.join"), none = B.newLabel("union.box.none");
|
|
4870
5015
|
const labels = arms.map(() => B.newLabel("union.box.arm"));
|
|
4871
5016
|
B.terminate(`switch i32 ${tag}, label %${none} [ ${labels.map((label, armTag) => `i32 ${armTag}, label %${label}`).join(" ")} ]`);
|
|
@@ -4972,6 +5117,12 @@ export class LlEmitter {
|
|
|
4972
5117
|
canBorrowCallArgument(value) {
|
|
4973
5118
|
if (value.kind === "strLit")
|
|
4974
5119
|
return true;
|
|
5120
|
+
// An exact capsule owns its instance while the capsule's binding holds it.
|
|
5121
|
+
if (value.kind === "dynCheck" && value.exact)
|
|
5122
|
+
return value.value.kind === "varRef" && this.canBorrowCallArgument(value.value);
|
|
5123
|
+
// An inline union field has no box to lend.
|
|
5124
|
+
if (this.inlineFieldGet(value))
|
|
5125
|
+
return false;
|
|
4975
5126
|
// Class casts reinterpret the same pointer (prefix layouts).
|
|
4976
5127
|
if ((value.kind === "upcast" || value.kind === "downcast") &&
|
|
4977
5128
|
value.value.type.kind === "object")
|
|
@@ -5484,6 +5635,24 @@ export class LlEmitter {
|
|
|
5484
5635
|
emitBorrowedArrayRead(this, s.init, b.slot);
|
|
5485
5636
|
break;
|
|
5486
5637
|
}
|
|
5638
|
+
const holeRead = this.loopArrayBorrows.has(s) ? dynHoleRead(s.init) : null;
|
|
5639
|
+
if (holeRead && s.init.kind === "ternary") {
|
|
5640
|
+
// A hole reads as the immortal undefined value, which needs no owner.
|
|
5641
|
+
const present = this.emitExpr(s.init.cond);
|
|
5642
|
+
const filled = B.newLabel("borrow.hole.filled"), missing = B.newLabel("borrow.hole.missing"), done = B.newLabel("borrow.hole.done");
|
|
5643
|
+
B.condBr(present.name, filled, missing);
|
|
5644
|
+
B.startBlock(filled);
|
|
5645
|
+
emitBorrowedArrayRead(this, holeRead, b.slot);
|
|
5646
|
+
B.br(done);
|
|
5647
|
+
B.startBlock(missing);
|
|
5648
|
+
this.declare("declare ptr @scr_dyn_undefined()");
|
|
5649
|
+
const undef = B.tmp();
|
|
5650
|
+
B.line(`${undef} = call ptr @scr_dyn_undefined()`);
|
|
5651
|
+
B.line(`store ptr ${undef}, ptr ${b.slot}`);
|
|
5652
|
+
B.br(done);
|
|
5653
|
+
B.startBlock(done);
|
|
5654
|
+
break;
|
|
5655
|
+
}
|
|
5487
5656
|
// A stable lexical alias cannot outlive its unchanged local owner.
|
|
5488
5657
|
// Whole-value uses still retain their own copies, so returning or
|
|
5489
5658
|
// storing the alias preserves the ordinary heap representation.
|
|
@@ -5542,10 +5711,9 @@ export class LlEmitter {
|
|
|
5542
5711
|
storeLocalUnion(this, localStorage, s.value);
|
|
5543
5712
|
break;
|
|
5544
5713
|
}
|
|
5545
|
-
const
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
this.emitStringSelfConcatAssign(s.localId, concat.left, suffix, false);
|
|
5714
|
+
const self = matchStringSelfConcat(s.localId, s.value);
|
|
5715
|
+
if (self) {
|
|
5716
|
+
this.emitStringSelfConcatAssign(s.localId, self.left, self.suffix, false);
|
|
5549
5717
|
break;
|
|
5550
5718
|
}
|
|
5551
5719
|
const b = this.binding(s.localId);
|
|
@@ -5646,7 +5814,7 @@ export class LlEmitter {
|
|
|
5646
5814
|
B.line(`${lenPtr} = getelementptr inbounds %ScrArr, ptr ${arr.name}, i32 0, i32 1`);
|
|
5647
5815
|
this.markMemoryPointer(lenPtr, "array:header");
|
|
5648
5816
|
B.line(`${len} = load ${this.sizeType}, ptr ${lenPtr}${this.fieldAliasAttachment(lenPtr)}`);
|
|
5649
|
-
B.line(`${lenNumber} =
|
|
5817
|
+
B.line(`${lenNumber} = ${sizeToDouble(this.sizeType)} ${this.sizeType} ${len} to double`);
|
|
5650
5818
|
B.line(`${same} = fcmp oeq double ${length.name}, ${lenNumber}`);
|
|
5651
5819
|
B.condBr(same, done, resize);
|
|
5652
5820
|
B.startBlock(resize);
|
|
@@ -5710,24 +5878,17 @@ export class LlEmitter {
|
|
|
5710
5878
|
break;
|
|
5711
5879
|
}
|
|
5712
5880
|
const obj = this.emitStableReceiver(s.obj, [s.value]);
|
|
5713
|
-
const v = this.
|
|
5881
|
+
const v = this.emitFieldValue(s.value, s.kind === "recordSet"
|
|
5882
|
+
? this.recordFieldInline(s.shapeId, s.field)
|
|
5883
|
+
: this.inlineUnions.classField(s.className, s.field));
|
|
5714
5884
|
if (s.kind === "fieldSet")
|
|
5715
5885
|
this.emitStoreGuard(obj.name, s);
|
|
5716
5886
|
else if (this.publishedTypes?.recordGuarded(s.shapeId) === true)
|
|
5717
5887
|
this.emitPublishedFieldGuard(obj.name, null, s.field);
|
|
5718
|
-
const { ptr, type } = s.kind === "fieldSet"
|
|
5888
|
+
const { ptr, type, inline } = s.kind === "fieldSet"
|
|
5719
5889
|
? this.classFieldPtr(obj.name, s.className, s.field)
|
|
5720
5890
|
: this.recordFieldPtr(obj.name, s.shapeId, s.field);
|
|
5721
|
-
|
|
5722
|
-
this.moveTemp(v);
|
|
5723
|
-
const old = B.tmp();
|
|
5724
|
-
B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
5725
|
-
this.storeField(ptr, type, v.name);
|
|
5726
|
-
this.releaseValue(old, type);
|
|
5727
|
-
}
|
|
5728
|
-
else {
|
|
5729
|
-
this.storeField(ptr, type, v.name);
|
|
5730
|
-
}
|
|
5891
|
+
this.replaceField(ptr, type, inline, v);
|
|
5731
5892
|
if (s.kind === "fieldSet" &&
|
|
5732
5893
|
s.field === "name" &&
|
|
5733
5894
|
this.classMeta.get(s.className)?.root.def.name === "%Error") {
|
|
@@ -5828,15 +5989,20 @@ export class LlEmitter {
|
|
|
5828
5989
|
const lw = B.newLabel("rks.w");
|
|
5829
5990
|
B.condBr(pend, join, lw);
|
|
5830
5991
|
B.startBlock(lw);
|
|
5831
|
-
const { ptr, type } = this.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
5832
|
-
if (
|
|
5992
|
+
const { ptr, type, inline } = this.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
5993
|
+
if (inline) {
|
|
5994
|
+
// The slot copies the checked value's bits; nv is released below.
|
|
5995
|
+
this.storeField(ptr, type, nv, true);
|
|
5996
|
+
this.releaseValue(nv, type);
|
|
5997
|
+
}
|
|
5998
|
+
else if (isRefCounted(type)) {
|
|
5833
5999
|
const old = B.tmp();
|
|
5834
6000
|
B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
5835
|
-
this.storeField(ptr, type, nv);
|
|
6001
|
+
this.storeField(ptr, type, nv, false);
|
|
5836
6002
|
this.releaseValue(old, type);
|
|
5837
6003
|
}
|
|
5838
6004
|
else {
|
|
5839
|
-
this.storeField(ptr, type, nv);
|
|
6005
|
+
this.storeField(ptr, type, nv, false);
|
|
5840
6006
|
}
|
|
5841
6007
|
B.br(join);
|
|
5842
6008
|
B.startBlock(ln);
|
|
@@ -5859,15 +6025,20 @@ export class LlEmitter {
|
|
|
5859
6025
|
const ln = B.newLabel("rks.n");
|
|
5860
6026
|
B.condBr(hit, lh, ln);
|
|
5861
6027
|
B.startBlock(lh);
|
|
5862
|
-
const { ptr, type } = this.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
5863
|
-
if (
|
|
6028
|
+
const { ptr, type, inline } = this.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
6029
|
+
if (inline) {
|
|
6030
|
+
// The write owns the moved-in value; the slot copies its bits.
|
|
6031
|
+
this.storeField(ptr, type, v.name, true);
|
|
6032
|
+
this.releaseValue(v.name, type);
|
|
6033
|
+
}
|
|
6034
|
+
else if (isRefCounted(type)) {
|
|
5864
6035
|
const old = B.tmp();
|
|
5865
6036
|
B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
5866
|
-
this.storeField(ptr, type, v.name);
|
|
6037
|
+
this.storeField(ptr, type, v.name, false);
|
|
5867
6038
|
this.releaseValue(old, type);
|
|
5868
6039
|
}
|
|
5869
6040
|
else {
|
|
5870
|
-
this.storeField(ptr, type, v.name);
|
|
6041
|
+
this.storeField(ptr, type, v.name, false);
|
|
5871
6042
|
}
|
|
5872
6043
|
B.br(join);
|
|
5873
6044
|
B.startBlock(ln);
|
|
@@ -5935,15 +6106,15 @@ export class LlEmitter {
|
|
|
5935
6106
|
const lc = B.newLabel("loop.c");
|
|
5936
6107
|
const lb = B.newLabel("loop.b");
|
|
5937
6108
|
const le = B.newLabel("loop.e");
|
|
6109
|
+
const lp = workerBudget !== null ? B.newLabel("loop.p") : lc;
|
|
5938
6110
|
B.br(lc);
|
|
5939
6111
|
B.startBlock(lc);
|
|
5940
|
-
this.emitWorkerLoopCheck(workerBudget);
|
|
5941
6112
|
B.condBr(this.emitCondition(s.cond), lb, le);
|
|
5942
6113
|
B.startBlock(lb);
|
|
5943
6114
|
this.jumpTargets.push({
|
|
5944
6115
|
kind: "loop",
|
|
5945
6116
|
brkLabel: le,
|
|
5946
|
-
contLabel:
|
|
6117
|
+
contLabel: lp,
|
|
5947
6118
|
labels: s.labels,
|
|
5948
6119
|
frameDepth: this.frames.length,
|
|
5949
6120
|
scopeDepth: this.scopes.length,
|
|
@@ -5951,7 +6122,12 @@ export class LlEmitter {
|
|
|
5951
6122
|
});
|
|
5952
6123
|
this.emitBlock(s.body);
|
|
5953
6124
|
this.jumpTargets.pop();
|
|
5954
|
-
B.br(
|
|
6125
|
+
B.br(lp);
|
|
6126
|
+
if (lp !== lc) {
|
|
6127
|
+
B.startBlock(lp);
|
|
6128
|
+
this.emitWorkerLoopCheck(workerBudget);
|
|
6129
|
+
B.br(lc);
|
|
6130
|
+
}
|
|
5955
6131
|
B.startBlock(le);
|
|
5956
6132
|
break;
|
|
5957
6133
|
}
|
|
@@ -5963,7 +6139,6 @@ export class LlEmitter {
|
|
|
5963
6139
|
const le = B.newLabel("loop.e");
|
|
5964
6140
|
B.br(lb);
|
|
5965
6141
|
B.startBlock(lb);
|
|
5966
|
-
this.emitWorkerLoopCheck(workerBudget);
|
|
5967
6142
|
this.jumpTargets.push({
|
|
5968
6143
|
kind: "loop",
|
|
5969
6144
|
brkLabel: le,
|
|
@@ -5977,6 +6152,7 @@ export class LlEmitter {
|
|
|
5977
6152
|
this.jumpTargets.pop();
|
|
5978
6153
|
B.br(lc);
|
|
5979
6154
|
B.startBlock(lc);
|
|
6155
|
+
this.emitWorkerLoopCheck(workerBudget);
|
|
5980
6156
|
B.condBr(this.emitCondition(s.cond), lb, le);
|
|
5981
6157
|
B.startBlock(le);
|
|
5982
6158
|
break;
|
|
@@ -6136,12 +6312,11 @@ export class LlEmitter {
|
|
|
6136
6312
|
B.line(`store ptr ${fresh}, ptr ${slot}`);
|
|
6137
6313
|
}
|
|
6138
6314
|
};
|
|
6139
|
-
const lu = s.update || capturedLets.length > 0 ? B.newLabel("loop.u") : lc;
|
|
6140
|
-
freshenBindings();
|
|
6141
6315
|
const workerBudget = this.workerLoopBudget(s);
|
|
6316
|
+
const lu = s.update || capturedLets.length > 0 || workerBudget !== null ? B.newLabel("loop.u") : lc;
|
|
6317
|
+
freshenBindings();
|
|
6142
6318
|
B.br(lc);
|
|
6143
6319
|
B.startBlock(lc);
|
|
6144
|
-
this.emitWorkerLoopCheck(workerBudget);
|
|
6145
6320
|
if (integerLoop && integerSlot) {
|
|
6146
6321
|
const receiver = this.emitStableReceiver(integerLoop.limitReceiver, []);
|
|
6147
6322
|
const lenPtr = B.tmp();
|
|
@@ -6182,6 +6357,7 @@ export class LlEmitter {
|
|
|
6182
6357
|
B.br(lu);
|
|
6183
6358
|
if (lu !== lc) {
|
|
6184
6359
|
B.startBlock(lu);
|
|
6360
|
+
this.emitWorkerLoopCheck(workerBudget);
|
|
6185
6361
|
freshenBindings();
|
|
6186
6362
|
if (integerLoop && integerSlot) {
|
|
6187
6363
|
const old = B.tmp();
|
|
@@ -6249,7 +6425,6 @@ export class LlEmitter {
|
|
|
6249
6425
|
const workerBudget = this.workerLoopBudget(s);
|
|
6250
6426
|
B.br(lc);
|
|
6251
6427
|
B.startBlock(lc);
|
|
6252
|
-
this.emitWorkerLoopCheck(workerBudget);
|
|
6253
6428
|
const inBounds = B.tmp();
|
|
6254
6429
|
let cur;
|
|
6255
6430
|
if (snapshot && cursor && scratch) {
|
|
@@ -6265,7 +6440,7 @@ export class LlEmitter {
|
|
|
6265
6440
|
B.line(`${lenPtr} = getelementptr inbounds %ScrArr, ptr ${arr.name}, i32 0, i32 1`);
|
|
6266
6441
|
this.markMemoryPointer(lenPtr, "array:header");
|
|
6267
6442
|
B.line(`${rawLen} = load ${this.sizeType}, ptr ${lenPtr}${this.fieldAliasAttachment(lenPtr)}`);
|
|
6268
|
-
B.line(`${len} =
|
|
6443
|
+
B.line(`${len} = ${sizeToDouble(this.sizeType)} ${this.sizeType} ${rawLen} to double`);
|
|
6269
6444
|
B.line(`${inBounds} = fcmp olt double ${i}, ${len}`);
|
|
6270
6445
|
cur = i;
|
|
6271
6446
|
}
|
|
@@ -6323,6 +6498,7 @@ export class LlEmitter {
|
|
|
6323
6498
|
this.jumpTargets.pop();
|
|
6324
6499
|
B.br(lu);
|
|
6325
6500
|
B.startBlock(lu);
|
|
6501
|
+
this.emitWorkerLoopCheck(workerBudget);
|
|
6326
6502
|
if (idxSlot) {
|
|
6327
6503
|
const i2 = B.tmp(), i3 = B.tmp();
|
|
6328
6504
|
B.line(`${i2} = load double, ptr ${idxSlot}`);
|
|
@@ -6528,7 +6704,7 @@ export class LlEmitter {
|
|
|
6528
6704
|
break;
|
|
6529
6705
|
default: {
|
|
6530
6706
|
// Statement coverage is now total (bytesSet closed the set) —
|
|
6531
|
-
// keep
|
|
6707
|
+
// keep throwing LlvmUnsupportedError for any future IR statement kind.
|
|
6532
6708
|
const rest = s;
|
|
6533
6709
|
const k = rest.kind;
|
|
6534
6710
|
throw new LlvmUnsupportedError(`stmt:${k}`, rest.loc);
|
|
@@ -6874,7 +7050,11 @@ export class LlEmitter {
|
|
|
6874
7050
|
if (e.kind === "seqExpr" &&
|
|
6875
7051
|
isRefCounted(e.result.type) &&
|
|
6876
7052
|
e.result.kind !== "strLit" &&
|
|
6877
|
-
this.discardableRead(e.result)
|
|
7053
|
+
(this.discardableRead(e.result) ||
|
|
7054
|
+
// A function-local binding's read has no effect of its own (a
|
|
7055
|
+
// compound assignment's result, say); a module binding's read may
|
|
7056
|
+
// throw before initialization, so it stays.
|
|
7057
|
+
(e.result.kind === "varRef" && this.binding(e.result.localId).kind === "local"))) {
|
|
6878
7058
|
this.emitSequence(() => {
|
|
6879
7059
|
for (const s of e.stmts)
|
|
6880
7060
|
this.emitStmt(s);
|
|
@@ -6905,8 +7085,11 @@ export class LlEmitter {
|
|
|
6905
7085
|
// of first building the suffix as a separate string.
|
|
6906
7086
|
const parts = stringParts(suffix);
|
|
6907
7087
|
const mixed = parts.length > 1 || numberPart(parts[0]) !== null;
|
|
7088
|
+
const charCode = mixed ? null : this.emitSingleCharCode(suffix);
|
|
6908
7089
|
const inputs = mixed ? emitConcatInputs(this, parts) : [];
|
|
6909
|
-
|
|
7090
|
+
// The concat only reads the suffix; relinquishing the binding below
|
|
7091
|
+
// runs no code that could rebind a borrowed local.
|
|
7092
|
+
const right = mixed || charCode !== null ? null : emitStringInputs(this, [suffix])[0];
|
|
6910
7093
|
const b = this.binding(localId);
|
|
6911
7094
|
const B = this.B;
|
|
6912
7095
|
if (b.kind === "boxed") {
|
|
@@ -6920,7 +7103,14 @@ export class LlEmitter {
|
|
|
6920
7103
|
this.releaseValue(old, b.type);
|
|
6921
7104
|
}
|
|
6922
7105
|
let raw;
|
|
6923
|
-
if (
|
|
7106
|
+
if (charCode !== null) {
|
|
7107
|
+
// The snapshot moves into the consuming character append.
|
|
7108
|
+
this.moveTemp(snapshot);
|
|
7109
|
+
this.declare(`declare ptr @scr_str_concat_move_char_code(ptr, double)`);
|
|
7110
|
+
raw = B.tmp();
|
|
7111
|
+
B.line(`${raw} = call ptr @scr_str_concat_move_char_code(ptr ${snapshot.name}, double ${charCode.name})`);
|
|
7112
|
+
}
|
|
7113
|
+
else if (right === null) {
|
|
6924
7114
|
raw = emitMixedConcat(this, snapshot.name, inputs);
|
|
6925
7115
|
}
|
|
6926
7116
|
else {
|
|
@@ -6945,6 +7135,17 @@ export class LlEmitter {
|
|
|
6945
7135
|
}
|
|
6946
7136
|
return result;
|
|
6947
7137
|
}
|
|
7138
|
+
/** The code of a one-argument `String.fromCharCode(c)` suffix, emitted, so
|
|
7139
|
+
* `s += String.fromCharCode(c)` appends the character without building
|
|
7140
|
+
* the one-character string; null for any other suffix. */
|
|
7141
|
+
emitSingleCharCode(suffix) {
|
|
7142
|
+
if (suffix.kind !== "libCall" || suffix.fn !== "string.fromCharCode")
|
|
7143
|
+
return null;
|
|
7144
|
+
const packed = suffix.args[0];
|
|
7145
|
+
if (packed?.kind !== "arrayLit" || packed.elems.length !== 1 || packed.spreads?.length)
|
|
7146
|
+
return null;
|
|
7147
|
+
return this.emitExpr(packed.elems[0]);
|
|
7148
|
+
}
|
|
6948
7149
|
/** `local = local + suffix` when the suffix cannot read or write the
|
|
6949
7150
|
* local (an unboxed binding is only reachable through this function's own
|
|
6950
7151
|
* expressions): reading the binding after the suffix gives the value the
|
|
@@ -6964,14 +7165,21 @@ export class LlEmitter {
|
|
|
6964
7165
|
return null;
|
|
6965
7166
|
const parts = stringParts(suffix);
|
|
6966
7167
|
const mixed = parts.length > 1 || numberPart(parts[0]) !== null;
|
|
7168
|
+
const charCode = mixed ? null : this.emitSingleCharCode(suffix);
|
|
6967
7169
|
const inputs = mixed ? emitConcatInputs(this, parts) : [];
|
|
6968
|
-
|
|
7170
|
+
// The concat only reads the suffix, which may stay borrowed.
|
|
7171
|
+
const right = mixed || charCode !== null ? null : emitStringInputs(this, [suffix])[0];
|
|
6969
7172
|
this.materializeSplitLocal(localId);
|
|
6970
7173
|
const B = this.B;
|
|
6971
7174
|
const head = B.tmp();
|
|
6972
7175
|
B.line(`${head} = load ptr, ptr ${b.slot}`);
|
|
6973
7176
|
let raw;
|
|
6974
|
-
if (
|
|
7177
|
+
if (charCode !== null) {
|
|
7178
|
+
this.declare(`declare ptr @scr_str_concat_move_char_code(ptr, double)`);
|
|
7179
|
+
raw = B.tmp();
|
|
7180
|
+
B.line(`${raw} = call ptr @scr_str_concat_move_char_code(ptr ${head}, double ${charCode.name})`);
|
|
7181
|
+
}
|
|
7182
|
+
else if (right === null) {
|
|
6975
7183
|
raw = emitMixedConcat(this, head, inputs, true);
|
|
6976
7184
|
}
|
|
6977
7185
|
else {
|
|
@@ -7007,8 +7215,122 @@ export class LlEmitter {
|
|
|
7007
7215
|
e.name === "region.leave" ||
|
|
7008
7216
|
e.name === "region.release")
|
|
7009
7217
|
return this.emitRegionIntrinsic(e);
|
|
7218
|
+
if (e.name.startsWith("itable."))
|
|
7219
|
+
return this.emitInternTableIntrinsic(e);
|
|
7010
7220
|
return emitIntrinsicExpr(this, e);
|
|
7011
7221
|
}
|
|
7222
|
+
/** InternTable's runtime calls (scr_itable.c). Table and entry handles
|
|
7223
|
+
* are f64 values carrying pointer bits; entry values are 64-bit slots
|
|
7224
|
+
* (double bits, a bool, or a pointer to an immortal value) that the
|
|
7225
|
+
* table neither retains nor releases. Lookups and inserts of array keys
|
|
7226
|
+
* throw a TypeError for keys longer than a table accepts. */
|
|
7227
|
+
emitInternTableIntrinsic(e) {
|
|
7228
|
+
const B = this.B;
|
|
7229
|
+
// The runtime copies keys and stores published values without counts,
|
|
7230
|
+
// so every operand is borrowed.
|
|
7231
|
+
const args = emitBorrowedInputs(this, e.args);
|
|
7232
|
+
if (B.isTerminated())
|
|
7233
|
+
return { name: "", type: e.type };
|
|
7234
|
+
const toPtr = (handle) => {
|
|
7235
|
+
const bits = B.tmp(), ptr = B.tmp();
|
|
7236
|
+
B.line(`${bits} = bitcast double ${handle} to i64`);
|
|
7237
|
+
B.line(`${ptr} = inttoptr i64 ${bits} to ptr`);
|
|
7238
|
+
return ptr;
|
|
7239
|
+
};
|
|
7240
|
+
const toHandle = (ptr) => {
|
|
7241
|
+
const bits = B.tmp(), handle = B.tmp();
|
|
7242
|
+
B.line(`${bits} = ptrtoint ptr ${ptr} to i64`);
|
|
7243
|
+
B.line(`${handle} = bitcast i64 ${bits} to double`);
|
|
7244
|
+
return { name: handle, type: e.type };
|
|
7245
|
+
};
|
|
7246
|
+
const keyCall = (op) => {
|
|
7247
|
+
const kind = e.args[1].type.kind;
|
|
7248
|
+
const key = kind === "string" ? "str" : kind === "array" ? "arr" : "f64";
|
|
7249
|
+
const keyTy = key === "f64" ? "double" : "ptr";
|
|
7250
|
+
const value = op === "insert" ? ", i64" : "";
|
|
7251
|
+
this.declare(`declare ptr @scr_itable_${op}_${key}(ptr, ${keyTy}${value})`);
|
|
7252
|
+
return `@scr_itable_${op}_${key}(ptr ${toPtr(args[0].name)}, ${keyTy} ${args[1].name}`;
|
|
7253
|
+
};
|
|
7254
|
+
switch (e.name) {
|
|
7255
|
+
case "itable.open": {
|
|
7256
|
+
this.declare(`declare ptr @scr_itable_open(ptr, i32)`);
|
|
7257
|
+
const kind = B.tmp(), table = B.tmp();
|
|
7258
|
+
B.line(`${kind} = fptosi double ${args[1].name} to i32`);
|
|
7259
|
+
B.line(`${table} = call ptr @scr_itable_open(ptr ${args[0].name}, i32 ${kind})`);
|
|
7260
|
+
return toHandle(table);
|
|
7261
|
+
}
|
|
7262
|
+
case "itable.find": {
|
|
7263
|
+
const call = keyCall("find");
|
|
7264
|
+
const entry = B.tmp();
|
|
7265
|
+
B.line(`${entry} = call ptr ${call})`);
|
|
7266
|
+
// Array keys longer than a table accepts throw a TypeError.
|
|
7267
|
+
if (e.args[1].type.kind === "array")
|
|
7268
|
+
this.emitPendingCheck();
|
|
7269
|
+
return toHandle(entry);
|
|
7270
|
+
}
|
|
7271
|
+
case "itable.insert": {
|
|
7272
|
+
const value = args[2];
|
|
7273
|
+
const ty = this.llType(value.type);
|
|
7274
|
+
let slot = value.name;
|
|
7275
|
+
if (ty === "double") {
|
|
7276
|
+
slot = B.tmp();
|
|
7277
|
+
B.line(`${slot} = bitcast double ${value.name} to i64`);
|
|
7278
|
+
}
|
|
7279
|
+
else if (ty === "i1") {
|
|
7280
|
+
slot = B.tmp();
|
|
7281
|
+
B.line(`${slot} = zext i1 ${value.name} to i64`);
|
|
7282
|
+
}
|
|
7283
|
+
else if (ty === "ptr") {
|
|
7284
|
+
slot = B.tmp();
|
|
7285
|
+
B.line(`${slot} = ptrtoint ptr ${value.name} to i64`);
|
|
7286
|
+
}
|
|
7287
|
+
else
|
|
7288
|
+
throw new InternalCompilerError(`llvm emitter bug: itable value of type ${ty}`);
|
|
7289
|
+
const call = keyCall("insert");
|
|
7290
|
+
const entry = B.tmp();
|
|
7291
|
+
B.line(`${entry} = call ptr ${call}, i64 ${slot})`);
|
|
7292
|
+
if (e.args[1].type.kind === "array")
|
|
7293
|
+
this.emitPendingCheck();
|
|
7294
|
+
return toHandle(entry);
|
|
7295
|
+
}
|
|
7296
|
+
case "itable.value": {
|
|
7297
|
+
// The handle's bits reach the address through memory: at -O0, x86
|
|
7298
|
+
// FastISel folds inttoptr(bitcast double) into the load's address
|
|
7299
|
+
// without moving the value out of its XMM register. Optimized
|
|
7300
|
+
// builds turn the stack round trip back into one register move.
|
|
7301
|
+
const carrier = B.slot();
|
|
7302
|
+
B.entryAllocas.push(`${carrier} = alloca double`);
|
|
7303
|
+
B.line(`store double ${args[0].name}, ptr ${carrier}`);
|
|
7304
|
+
const bits = B.tmp(), entry = B.tmp();
|
|
7305
|
+
B.line(`${bits} = load i64, ptr ${carrier}`);
|
|
7306
|
+
B.line(`${entry} = inttoptr i64 ${bits} to ptr`);
|
|
7307
|
+
const slot = B.tmp();
|
|
7308
|
+
B.line(`${slot} = load i64, ptr ${entry}, align 8`);
|
|
7309
|
+
const ty = this.llType(e.type);
|
|
7310
|
+
const result = B.tmp();
|
|
7311
|
+
if (ty === "double")
|
|
7312
|
+
B.line(`${result} = bitcast i64 ${slot} to double`);
|
|
7313
|
+
else if (ty === "i1")
|
|
7314
|
+
B.line(`${result} = trunc i64 ${slot} to i1`);
|
|
7315
|
+
else if (ty === "ptr")
|
|
7316
|
+
B.line(`${result} = inttoptr i64 ${slot} to ptr`);
|
|
7317
|
+
else
|
|
7318
|
+
throw new InternalCompilerError(`llvm emitter bug: itable value of type ${ty}`);
|
|
7319
|
+
// Stored values are immortal: owning one adds no count.
|
|
7320
|
+
return isRefCounted(e.type)
|
|
7321
|
+
? this.own({ name: result, type: e.type })
|
|
7322
|
+
: { name: result, type: e.type };
|
|
7323
|
+
}
|
|
7324
|
+
case "itable.size": {
|
|
7325
|
+
this.declare(`declare double @scr_itable_size(ptr)`);
|
|
7326
|
+
const size = B.tmp();
|
|
7327
|
+
B.line(`${size} = call double @scr_itable_size(ptr ${toPtr(args[0].name)})`);
|
|
7328
|
+
return { name: size, type: e.type };
|
|
7329
|
+
}
|
|
7330
|
+
default:
|
|
7331
|
+
throw new InternalCompilerError(`llvm emitter bug: unknown intrinsic ${e.name}`);
|
|
7332
|
+
}
|
|
7333
|
+
}
|
|
7012
7334
|
/** Lifetime regions in modules with lifetimeRegions (llvm/regions.ts).
|
|
7013
7335
|
* Created with the class graph; null elsewhere. */
|
|
7014
7336
|
regions = null;
|
|
@@ -7054,6 +7376,7 @@ export class LlEmitter {
|
|
|
7054
7376
|
tracedShapes: this.tracedShapes,
|
|
7055
7377
|
unionsById: this.unionsById,
|
|
7056
7378
|
recordsById: this.recordsById,
|
|
7379
|
+
inlineUnions: this.inlineUnions,
|
|
7057
7380
|
nullableArm: (t) => this.nullableUnions.of(t)?.arm ?? null,
|
|
7058
7381
|
classInfo: (className) => {
|
|
7059
7382
|
const meta = this.classMetaOf(className);
|
|
@@ -7063,11 +7386,16 @@ export class LlEmitter {
|
|
|
7063
7386
|
pre: meta.pre,
|
|
7064
7387
|
post: meta.post,
|
|
7065
7388
|
runtimeRooted: meta.root.def.runtime === true,
|
|
7066
|
-
fields:
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7389
|
+
// Inline scalar-union fields are plain bits: nothing to push.
|
|
7390
|
+
fields: meta.def.fields.flatMap((f) => this.inlineUnions.classField(className, f.name)
|
|
7391
|
+
? []
|
|
7392
|
+
: [
|
|
7393
|
+
{
|
|
7394
|
+
name: f.name,
|
|
7395
|
+
index: classFieldIndex(meta, f.name).index,
|
|
7396
|
+
type: this.nullableFields.storageType(className, f.name, f.type),
|
|
7397
|
+
},
|
|
7398
|
+
]),
|
|
7071
7399
|
};
|
|
7072
7400
|
},
|
|
7073
7401
|
classesInInterval: (pre, post) => byPre.filter((m) => m.pre >= pre && m.pre <= post).map((m) => m.def.name),
|
|
@@ -7234,6 +7562,8 @@ export class LlEmitter {
|
|
|
7234
7562
|
this.B.line(`${value} = load ptr, ptr ${binding.slot}`);
|
|
7235
7563
|
return { name: value, type: e.type };
|
|
7236
7564
|
}
|
|
7565
|
+
if (e.kind === "dynCheck" && e.exact)
|
|
7566
|
+
return this.emitExactCapsuleObject(e.value, e.type);
|
|
7237
7567
|
if (e.kind === "chainRecv") {
|
|
7238
7568
|
// The chain's bind slot holds its receiver unchanged until the body
|
|
7239
7569
|
// finishes, owned by the slot itself or by the chain's receiver.
|
|
@@ -7294,13 +7624,14 @@ export class LlEmitter {
|
|
|
7294
7624
|
if (e.kind === "recordGet" || e.kind === "fieldGet") {
|
|
7295
7625
|
const receiver = this.emitReadReceiver(e.obj);
|
|
7296
7626
|
if (e.kind === "recordGet") {
|
|
7297
|
-
|
|
7298
|
-
|
|
7627
|
+
// An inline union field answers a private stack box.
|
|
7628
|
+
const { ptr, type, inline } = this.recordFieldPtr(receiver.name, e.shapeId, e.field);
|
|
7629
|
+
return { name: this.loadRecordField(ptr, type, inline), type: e.type };
|
|
7299
7630
|
}
|
|
7300
|
-
const { ptr, type } = this.classFieldPtr(receiver.name, e.className, e.field);
|
|
7631
|
+
const { ptr, type, inline } = this.classFieldPtr(receiver.name, e.className, e.field);
|
|
7301
7632
|
if (this.int32Slots.isField(e.className, e.field))
|
|
7302
7633
|
return this.loadInt32Field(ptr, e.type);
|
|
7303
|
-
return { name: this.loadField(ptr, type), type: e.type };
|
|
7634
|
+
return { name: this.loadField(ptr, type, inline), type: e.type };
|
|
7304
7635
|
}
|
|
7305
7636
|
if (e.kind === "ternary" && this.canBorrowReceiver(e.then) && this.canBorrowReceiver(e.else_)) {
|
|
7306
7637
|
// Checked projections lower to a ternary with an always-throwing
|
|
@@ -7364,7 +7695,15 @@ export class LlEmitter {
|
|
|
7364
7695
|
matchMapRead(e, this.boxedUnionsById) !== null ||
|
|
7365
7696
|
this.optionalArrayReads.get(e) !== null ||
|
|
7366
7697
|
isScalarOptionalSource(e, this.unionSources) ||
|
|
7367
|
-
this.scalarResultCall(e)
|
|
7698
|
+
this.scalarResultCall(e) ||
|
|
7699
|
+
this.inlineFieldGet(e));
|
|
7700
|
+
}
|
|
7701
|
+
/** A read of a record or class field that stores its scalar union
|
|
7702
|
+
* inline. */
|
|
7703
|
+
inlineFieldGet(e) {
|
|
7704
|
+
if (e.kind === "recordGet")
|
|
7705
|
+
return this.recordFieldInline(e.shapeId, e.field);
|
|
7706
|
+
return e.kind === "fieldGet" && this.inlineUnions.classField(e.className, e.field);
|
|
7368
7707
|
}
|
|
7369
7708
|
/** The nullable-pointer representation behind a union-typed class field
|
|
7370
7709
|
* read, or null for every other expression. */
|
|
@@ -7503,6 +7842,15 @@ export class LlEmitter {
|
|
|
7503
7842
|
this.localArrayReads.has(localId) ||
|
|
7504
7843
|
this.mapReadLifetimes.locals.has(localId));
|
|
7505
7844
|
}
|
|
7845
|
+
/** The instance of a capsule known to hold exactly this class (borrowed). */
|
|
7846
|
+
emitExactCapsuleObject(value, type) {
|
|
7847
|
+
const capsule = this.emitReadReceiver(value);
|
|
7848
|
+
const slot = this.B.tmp();
|
|
7849
|
+
const object = this.B.tmp();
|
|
7850
|
+
this.B.line(`${slot} = getelementptr inbounds i8, ptr ${capsule.name}, i64 16 ; ->v.typed_ref.ptr`);
|
|
7851
|
+
this.B.line(`${object} = load ptr, ptr ${slot}`);
|
|
7852
|
+
return { name: object, type };
|
|
7853
|
+
}
|
|
7506
7854
|
canBorrowReceiver(e) {
|
|
7507
7855
|
switch (e.kind) {
|
|
7508
7856
|
case "chainRecv":
|
|
@@ -7520,9 +7868,11 @@ export class LlEmitter {
|
|
|
7520
7868
|
case "downcast":
|
|
7521
7869
|
case "upcast":
|
|
7522
7870
|
return this.canBorrowReceiver(e.value);
|
|
7871
|
+
// An inline union field has no box to lend: projections read it
|
|
7872
|
+
// through emitReadReceiver's private stack box.
|
|
7523
7873
|
case "fieldGet":
|
|
7524
7874
|
case "recordGet":
|
|
7525
|
-
return this.canBorrowReceiver(e.obj);
|
|
7875
|
+
return !this.inlineFieldGet(e) && this.canBorrowReceiver(e.obj);
|
|
7526
7876
|
case "ternary":
|
|
7527
7877
|
return this.canBorrowReceiver(e.then) && this.canBorrowReceiver(e.else_);
|
|
7528
7878
|
case "seqExpr": {
|
|
@@ -7758,8 +8108,11 @@ export class LlEmitter {
|
|
|
7758
8108
|
fsRenameThunkFor(cbT) {
|
|
7759
8109
|
return fsRenameThunkFor(this, cbT);
|
|
7760
8110
|
}
|
|
7761
|
-
cryptoBytesThunkFor(cbT, arrayBuffer = false) {
|
|
7762
|
-
return cryptoBytesThunkFor(this, cbT, arrayBuffer);
|
|
8111
|
+
cryptoBytesThunkFor(cbT, arrayBuffer = false, valueMode = "buffer") {
|
|
8112
|
+
return cryptoBytesThunkFor(this, cbT, arrayBuffer, valueMode);
|
|
8113
|
+
}
|
|
8114
|
+
cryptoIntThunkFor(cbT) {
|
|
8115
|
+
return cryptoIntThunkFor(this, cbT);
|
|
7763
8116
|
}
|
|
7764
8117
|
zlibBytesThunkFor(cbT) {
|
|
7765
8118
|
return zlibBytesThunkFor(this, cbT);
|