@scriptc/compiler 0.3.2 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +490 -39
- package/dist/backend/cycle-analysis.js +6 -1
- package/dist/backend/cycle-analysis.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 +8 -1
- package/dist/backend/llvm/call-lifetimes.js +33 -11
- package/dist/backend/llvm/call-lifetimes.js.map +1 -1
- package/dist/backend/llvm/call-lifetimes.test.js +54 -0
- package/dist/backend/llvm/call-lifetimes.test.js.map +1 -1
- package/dist/backend/llvm/classes.js +87 -36
- package/dist/backend/llvm/classes.js.map +1 -1
- package/dist/backend/llvm/common.d.ts +1 -1
- package/dist/backend/llvm/common.js +1 -1
- package/dist/backend/llvm/dense-array-access.d.ts +5 -0
- package/dist/backend/llvm/dense-array-access.js +1 -1
- package/dist/backend/llvm/dense-array-access.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +4 -0
- package/dist/backend/llvm/dyn.js +73 -9
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.d.ts +65 -14
- package/dist/backend/llvm/emitter.js +297 -81
- 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.js +11 -0
- 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.js +8 -1
- package/dist/backend/llvm/expr-calls.js.map +1 -1
- package/dist/backend/llvm/expr-containers.js +42 -15
- 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/lib-dispatch.js +163 -28
- package/dist/backend/llvm/lib-dispatch.js.map +1 -1
- package/dist/backend/llvm/lib-filesystem.js +125 -7
- package/dist/backend/llvm/lib-filesystem.js.map +1 -1
- package/dist/backend/llvm/lib-network.js +9 -6
- package/dist/backend/llvm/lib-network.js.map +1 -1
- package/dist/backend/llvm/lib-process.js +2 -2
- package/dist/backend/llvm/lib-process.js.map +1 -1
- package/dist/backend/llvm/lib-shared.js +132 -0
- package/dist/backend/llvm/lib-shared.js.map +1 -1
- package/dist/backend/llvm/lib-stream.js +97 -0
- package/dist/backend/llvm/lib-stream.js.map +1 -1
- package/dist/backend/llvm/local-array-reads.js +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 +20 -0
- package/dist/backend/llvm/map-number-lookup.js +66 -0
- package/dist/backend/llvm/map-number-lookup.js.map +1 -1
- package/dist/backend/llvm/map-number-lookup.test.d.ts +1 -0
- package/dist/backend/llvm/map-number-lookup.test.js +102 -0
- package/dist/backend/llvm/map-number-lookup.test.js.map +1 -0
- package/dist/backend/llvm/map-read-lifetimes.js +1 -0
- package/dist/backend/llvm/map-read-lifetimes.js.map +1 -1
- package/dist/backend/llvm/publish.d.ts +4 -0
- package/dist/backend/llvm/publish.js +3 -1
- package/dist/backend/llvm/publish.js.map +1 -1
- package/dist/backend/llvm/record-results.d.ts +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 +14 -0
- package/dist/backend/llvm/reference-writes.js.map +1 -1
- package/dist/backend/llvm/regions.d.ts +1 -0
- package/dist/backend/llvm/regions.js +12 -7
- 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/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 +9 -4
- package/dist/backend/may-throw.js.map +1 -1
- package/dist/backend/native/contracts.d.ts +2 -2
- package/dist/backend/native/executable.js +14 -3
- 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 +1 -0
- package/dist/backend/native/runtime-inputs.js.map +1 -1
- package/dist/backend/native-toolchain.test.js +1 -1
- package/dist/backend/native-toolchain.test.js.map +1 -1
- package/dist/backend/runtime-abi.d.ts +2 -2
- package/dist/backend/runtime-abi.js +2 -2
- package/dist/backend/runtime-pack-targets.test.js +1 -1
- package/dist/backend/runtime-pack.test.js +1 -1
- package/dist/backend/target-diagnostics.js +4 -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/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/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/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.js +3 -2
- package/dist/frontend/lowering/builtins/compression.js.map +1 -1
- package/dist/frontend/lowering/builtins/crypto.js +415 -120
- package/dist/frontend/lowering/builtins/crypto.js.map +1 -1
- package/dist/frontend/lowering/builtins/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/url.d.ts +8 -0
- package/dist/frontend/lowering/builtins/url.js +36 -0
- package/dist/frontend/lowering/builtins/url.js.map +1 -1
- package/dist/frontend/lowering/call-arguments.js +1 -1
- package/dist/frontend/lowering/call-arguments.js.map +1 -1
- package/dist/frontend/lowering/call-signatures.js +20 -2
- package/dist/frontend/lowering/call-signatures.js.map +1 -1
- package/dist/frontend/lowering/class-dynamic-dispatch.d.ts +2 -0
- package/dist/frontend/lowering/class-dynamic-dispatch.js +105 -1
- 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/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 +2 -2
- package/dist/frontend/lowering/lower-async-iteration.d.ts +6 -3
- package/dist/frontend/lowering/lower-async-iteration.js +248 -2
- package/dist/frontend/lowering/lower-async-iteration.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +101 -9
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +8 -2
- package/dist/frontend/lowering/lower-classes.js +40 -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-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 +112 -22
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +129 -11
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-mixins.js +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +1 -1
- package/dist/frontend/lowering/lower-modules.js +7 -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.js +39 -14
- 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 +46 -12
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +234 -22
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lower-timers.js +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +23 -5
- package/dist/frontend/lowering/lowerer.js +245 -41
- 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/runtime-optional-records.d.ts +115 -0
- package/dist/frontend/lowering/runtime-optional-records.js +715 -0
- package/dist/frontend/lowering/runtime-optional-records.js.map +1 -0
- package/dist/frontend/lowering/runtime-optional-records.test.d.ts +1 -0
- package/dist/frontend/lowering/runtime-optional-records.test.js +175 -0
- package/dist/frontend/lowering/runtime-optional-records.test.js.map +1 -0
- package/dist/frontend/lowering/surfaces.d.ts +7 -3
- package/dist/frontend/lowering/surfaces.js +273 -22
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- 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 +1 -1
- package/dist/frontend/pipeline.js.map +1 -1
- package/dist/frontend/program.d.ts +3 -3
- package/dist/frontend/program.js +19 -17
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/resolve.js +1 -1
- package/dist/frontend/ts7/adapter.js +1 -1
- package/dist/frontend/ts7/ast-bytes.d.ts +1 -1
- package/dist/frontend/ts7/ast-bytes.js +1 -1
- package/dist/frontend/ts7/semantic-json.d.ts +1 -1
- package/dist/frontend/ts7/semantic-json.js +1 -1
- package/dist/frontend/ts7/semantic-json.js.map +1 -1
- package/dist/frontend/ts7/world-check.js +1 -1
- package/dist/frontend/tsc-codes.js +2 -2
- package/dist/frontend/tsc-codes.js.map +1 -1
- package/dist/frontend/type-mapper.d.ts +16 -1
- package/dist/frontend/type-mapper.js +143 -18
- package/dist/frontend/type-mapper.js.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/ir/analysis.d.ts +12 -6
- package/dist/ir/analysis.js +26 -10
- package/dist/ir/analysis.js.map +1 -1
- package/dist/ir/analysis.test.js +15 -3
- package/dist/ir/analysis.test.js.map +1 -1
- package/dist/ir/builtin-effects.js +79 -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 +291 -38
- 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 +64 -16
- package/dist/ir/ir.js +37 -1
- package/dist/ir/ir.js.map +1 -1
- package/dist/ir/runtime-features.js +83 -6
- 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 +100 -9
- 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 +10 -4
- package/dist/library/ir-policy.js.map +1 -1
- package/dist/library/library-profile.js +13 -13
- package/dist/library/library-profile.js.map +1 -1
- package/dist/library/prepare.js +1 -1
- package/dist/library/prepare.js.map +1 -1
- package/dist/library/sidecar.js +3 -3
- package/dist/library/sidecar.js.map +1 -1
- package/dist/native/prepare.js +3 -2
- package/dist/native/prepare.js.map +1 -1
- package/package.json +20 -20
- package/surface-manifest.json +379 -142
|
@@ -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,6 +42,7 @@ 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";
|
|
@@ -52,7 +55,7 @@ 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";
|
|
@@ -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";
|
|
@@ -89,10 +92,10 @@ 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();
|
|
@@ -439,6 +446,8 @@ export class LlEmitter {
|
|
|
439
446
|
* typeKey → thunk symbol. */
|
|
440
447
|
resolveThunks = new Map();
|
|
441
448
|
resolveThunkDefs = [];
|
|
449
|
+
/** Inline array searches used by the module (array-search.ts). */
|
|
450
|
+
arraySearchKinds = new Set();
|
|
442
451
|
/** Typed-ref recipe constants by type key (lazy receivers). */
|
|
443
452
|
typedRefRecipes = new Map();
|
|
444
453
|
/** ReadableStream.from adapters keep typed arrays by reference and box
|
|
@@ -452,6 +461,7 @@ export class LlEmitter {
|
|
|
452
461
|
dynPromiseAdapters = new Map();
|
|
453
462
|
unionsById = new Map();
|
|
454
463
|
nullableFields;
|
|
464
|
+
inlineUnions;
|
|
455
465
|
/** Unions whose values are nullable arm pointers (nullable-unions.ts). */
|
|
456
466
|
nullableUnions;
|
|
457
467
|
/** The union table without nullable unions: the stack-box analyses. */
|
|
@@ -624,7 +634,9 @@ export class LlEmitter {
|
|
|
624
634
|
this.emitLibraryIdentity = options.emitLibraryIdentity !== false;
|
|
625
635
|
this.runtimeAbiMarker = options.runtimeAbiMarker === true;
|
|
626
636
|
this.detachedExit = options.detachedExit === true;
|
|
627
|
-
this.rcHelpers = options.inlineRc
|
|
637
|
+
this.rcHelpers = options.inlineRc !== undefined ? new Set() : null;
|
|
638
|
+
this.rcMode = options.inlineRc;
|
|
639
|
+
this.rcHelpersNoinline = options.rcHelpersNoinline === true;
|
|
628
640
|
// ScrCycHdr.buf sits 4 bytes behind every object on every target.
|
|
629
641
|
this.cycleBufOffset = CYC_HDR - CYC_BUF;
|
|
630
642
|
this.ffiCallbackAdapters = allocateFfiCallbackAdapters(mod.ffiImports ?? []);
|
|
@@ -662,6 +674,9 @@ export class LlEmitter {
|
|
|
662
674
|
this.immortalValues.add("null");
|
|
663
675
|
this.immortalValues.add(NULLABLE_NULL);
|
|
664
676
|
this.nullableFields = new NullableRefFields(mod.classes ?? [], this.boxedUnionsById);
|
|
677
|
+
this.inlineUnions = new InlineUnionFields(this.boxedUnionsById, mod.classes ?? []);
|
|
678
|
+
for (const r of mod.records ?? [])
|
|
679
|
+
this.recordsById.set(r.id, r);
|
|
665
680
|
// Optional array reads also cover nullable unions: emitLocalArrayRead
|
|
666
681
|
// then yields the (borrowed or owned) element pointer, not a stack box.
|
|
667
682
|
// Arrays of such a union are read the same way.
|
|
@@ -670,6 +685,7 @@ export class LlEmitter {
|
|
|
670
685
|
unions: this.boxedUnionsById,
|
|
671
686
|
receiverUnions: this.unionsById,
|
|
672
687
|
nullableField: (e) => this.nullableFieldGet(e) !== null,
|
|
688
|
+
inlineField: (e) => this.inlineFieldGet(e),
|
|
673
689
|
arrayRead: (e) => this.optionalArrayReads.get(e) !== null,
|
|
674
690
|
scalarCall: (e) => this.scalarResultCall(e),
|
|
675
691
|
};
|
|
@@ -718,14 +734,15 @@ export class LlEmitter {
|
|
|
718
734
|
walkParameters.set(fn.name, indexes);
|
|
719
735
|
}
|
|
720
736
|
}
|
|
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))
|
|
737
|
+
this.callLifetimes = analyzeCallLifetimes(this.fnByName, (className, field) => this.nullableFields.get(className, field) !== null, walkParameters, new Set([...this.int32Abis].filter(([, abi]) => abi.union).map(([name]) => name)), {
|
|
738
|
+
record: (shapeId, field) => this.recordFieldInline(shapeId, field),
|
|
739
|
+
classField: (className, field) => this.inlineUnions.classField(className, field),
|
|
740
|
+
});
|
|
722
741
|
this.constantCallbacks = findConstantCallbacks(mod, this.callLifetimes);
|
|
723
742
|
this.stackCallbacks = new StackCallbacks(this.fnByName);
|
|
724
743
|
this.receiverReaders = new AmbientReceiverReaders(this.fnByName);
|
|
725
744
|
this.stackCaptures = new StackCaptures(this.fnByName, this.callLifetimes, this.stackCallbacks);
|
|
726
745
|
this.lazyCaptures = new LazyCaptures(this.fnByName);
|
|
727
|
-
for (const r of mod.records ?? [])
|
|
728
|
-
this.recordsById.set(r.id, r);
|
|
729
746
|
const traced = computeTraced(mod);
|
|
730
747
|
this.tracedShapes = traced.shapes;
|
|
731
748
|
this.tracedUnions = traced.unions;
|
|
@@ -735,6 +752,8 @@ export class LlEmitter {
|
|
|
735
752
|
tracedShapes: this.tracedShapes,
|
|
736
753
|
tracedUnions: this.tracedUnions,
|
|
737
754
|
nullableUnions: this.nullableUnions,
|
|
755
|
+
inlineUnions: this.inlineUnions,
|
|
756
|
+
unionNoneRef: () => this.unionNoneRef(),
|
|
738
757
|
recordsById: this.recordsById,
|
|
739
758
|
recordCloneShapes: this.recordCloneShapes,
|
|
740
759
|
objectAudit: options.objectAudit !== false,
|
|
@@ -748,6 +767,8 @@ export class LlEmitter {
|
|
|
748
767
|
// paths address its thread-local state.
|
|
749
768
|
threadLocalAlloc: mod.workers === true,
|
|
750
769
|
rcHelpers: this.rcHelpers,
|
|
770
|
+
...(this.rcMode !== undefined ? { rcMode: this.rcMode } : {}),
|
|
771
|
+
...(this.rcHelpersNoinline ? { rcHelpersNoinline: true } : {}),
|
|
751
772
|
nextCycKind: () => FIRST_EMITTED_CYC_KIND + this.cycKinds++,
|
|
752
773
|
unionsById: this.unionsById,
|
|
753
774
|
declare: (decl) => this.declare(decl),
|
|
@@ -763,6 +784,7 @@ export class LlEmitter {
|
|
|
763
784
|
liveDynUnionRefAdapter: (type) => this.liveDynUnionRefAdapter(type),
|
|
764
785
|
dynPromiseAdapter: (type) => this.dynPromiseAdapter(type),
|
|
765
786
|
isErrorClass: (name) => this.classMeta.get(name)?.root.def.name === "%Error",
|
|
787
|
+
classRootOf: (name) => this.classMeta.get(name)?.root.def.name,
|
|
766
788
|
classSubtypes: (name) => {
|
|
767
789
|
const target = this.classMetaOf(name);
|
|
768
790
|
const intervals = classMembershipIntervals(this.classMeta, target.def.name);
|
|
@@ -796,13 +818,16 @@ export class LlEmitter {
|
|
|
796
818
|
this.tdzGlobals.set(g.id, g.name);
|
|
797
819
|
}
|
|
798
820
|
this.stableGlobals = stableGlobals(mod);
|
|
799
|
-
// Runtime error, EventEmitter,
|
|
800
|
-
// Subclasses embed the
|
|
821
|
+
// Runtime error, EventEmitter, stream, EventTarget and Event classes
|
|
822
|
+
// have known layouts. Subclasses embed the runtime prefixes from
|
|
823
|
+
// classes.ts.
|
|
801
824
|
const classes = mod.classes ?? [];
|
|
802
825
|
for (const cls of classes) {
|
|
803
826
|
if (cls.runtime &&
|
|
804
827
|
!RUNTIME_ERROR_CLASSES.has(cls.name) &&
|
|
805
828
|
cls.name !== RUNTIME_EMITTER_CLASS &&
|
|
829
|
+
cls.name !== RUNTIME_EVENT_TARGET_CLASS &&
|
|
830
|
+
cls.name !== RUNTIME_EVENT_CLASS &&
|
|
806
831
|
!RUNTIME_STREAM_CLASSES.has(cls.name)) {
|
|
807
832
|
throw new LlvmUnsupportedError(`classDef:${cls.name}`, cls.loc);
|
|
808
833
|
}
|
|
@@ -1162,7 +1187,7 @@ export class LlEmitter {
|
|
|
1162
1187
|
return this.emitParts().join("\n");
|
|
1163
1188
|
}
|
|
1164
1189
|
emitParts() {
|
|
1165
|
-
const parts = this.emitModuleParts();
|
|
1190
|
+
const parts = limitInlineDynReleases(this.emitModuleParts());
|
|
1166
1191
|
if (!this.executableTls)
|
|
1167
1192
|
return parts;
|
|
1168
1193
|
// A worker executable's thread-locals all live in the executable's own
|
|
@@ -1215,7 +1240,7 @@ export class LlEmitter {
|
|
|
1215
1240
|
// Module globals, FIRST OCCURRENCE per id: a class-expression static
|
|
1216
1241
|
// instantiated through several mixin applications registers one global
|
|
1217
1242
|
// id several times (2041-mixin-values) — C's tentative definitions
|
|
1218
|
-
//
|
|
1243
|
+
// accept the duplicates without an error, LLVM rejects redefinition, so the
|
|
1219
1244
|
// storage AND the release emit once per id here.
|
|
1220
1245
|
const seenGlobalIds = new Set();
|
|
1221
1246
|
const globals = (this.mod.globals ?? []).filter((g) => {
|
|
@@ -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}`);
|
|
@@ -2158,6 +2198,15 @@ export class LlEmitter {
|
|
|
2158
2198
|
? ` %i = add i64 ${mapIndex.wide}, 0`
|
|
2159
2199
|
: ` %i = trunc i64 ${mapIndex.wide} to ${sz}`, ` %dp = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 19`, ` %dense = load ptr, ptr %dp`, ` %sp = getelementptr inbounds i32, ptr %dense, ${sz} %i`, ` %s = load i32, ptr %sp`, ` %empty = icmp eq i32 %s, 0`, ` br i1 %empty, label %miss, label %hit`, `hit:`, ` %e32 = sub i32 %s, 1`, sz === "i32" ? ` %e = add i32 %e32, 0` : ` %e = zext i32 %e32 to ${sz}`, ` %ep = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 13`, ` %entries = load ptr, ptr %ep`, ` %found = getelementptr inbounds %ScrMapEntry, ptr %entries, ${sz} %e`, ` ret ptr %found`, `miss:`, ` ret ptr null`, `outside:`, ` %dense.any = icmp ne ${sz} %nd, 0`, ` br i1 %dense.any, label %miss, label %slow`, `slow:`, ` %r = call ptr @scr_map_entry_f64(ptr %m, double %k)`, ` ret ptr %r`, `}`, ``);
|
|
2160
2200
|
}
|
|
2201
|
+
// Map/Set iteration steps read the entries array inline: an index is
|
|
2202
|
+
// live when it is below the entry count and its entry's cached hash is
|
|
2203
|
+
// nonzero (a tombstone's is zero), as scr_map_iter_live decides. The
|
|
2204
|
+
// entry count is read again at every step, so entries appended during
|
|
2205
|
+
// the iteration are visited.
|
|
2206
|
+
if (this.decls.has(MAP_ITER_DECL)) {
|
|
2207
|
+
const sz = this.sizeType;
|
|
2208
|
+
defs.push(`define internal ptr @sc_map_iter_entry(ptr %m, double %i) ${FN_ATTRS} {`, `entry:`, ` %np = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 9`, ` %n = load ${sz}, ptr %np`, ` %nf = uitofp ${sz} %n to double`, ` %lo = fcmp oge double %i, 0.0`, ` %hi = fcmp olt double %i, %nf`, ` %in = and i1 %lo, %hi`, ` br i1 %in, label %load, label %none`, `load:`, ` %ix = fptoui double %i to ${sz}`, ` %ep = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 13`, ` %entries = load ptr, ptr %ep`, ` %e = getelementptr inbounds %ScrMapEntry, ptr %entries, ${sz} %ix`, ` %hp = getelementptr inbounds %ScrMapEntry, ptr %e, i32 0, i32 2`, ` %h = load i64, ptr %hp`, ` %live = icmp ne i64 %h, 0`, ` br i1 %live, label %yes, label %none`, `yes:`, ` ret ptr %e`, `none:`, ` ret ptr null`, `}`, ``, `define internal double @sc_map_iter_count(ptr %m) ${FN_ATTRS} {`, `entry:`, ` %np = getelementptr inbounds %ScrMapIx, ptr %m, i32 0, i32 9`, ` %n = load ${sz}, ptr %np`, ` %nf = uitofp ${sz} %n to double`, ` ret double %nf`, `}`, ``);
|
|
2209
|
+
}
|
|
2161
2210
|
// String-key Map/Set lookups test the map's absent-key filter inline
|
|
2162
2211
|
// (scr_map.c scr_map_filter_bits): a key whose two filter bits are not
|
|
2163
2212
|
// both set is absent, so most misses on small and medium maps return
|
|
@@ -2398,7 +2447,7 @@ export class LlEmitter {
|
|
|
2398
2447
|
* programs keep fibers too: their fiber epilogue owns context
|
|
2399
2448
|
* termination (a stopping worker rejects and observes the promise), which
|
|
2400
2449
|
* the fiberless wrapper does not reproduce. A missed suspension still
|
|
2401
|
-
* cannot reorder
|
|
2450
|
+
* cannot reorder execution undetected: the runtime traps when a context parks while a
|
|
2402
2451
|
* fiberless body is on its stack. */
|
|
2403
2452
|
fiberlessAsyncFunctions() {
|
|
2404
2453
|
const eligible = new Set();
|
|
@@ -3050,8 +3099,13 @@ export class LlEmitter {
|
|
|
3050
3099
|
* holding the ABSENT state surfaces as the ordinary undefined arm, so
|
|
3051
3100
|
* absence never travels beyond its slot (a later `{ f: r.f }` is an
|
|
3052
3101
|
* explicit, present property). */
|
|
3053
|
-
loadRecordField(ptr, t) {
|
|
3054
|
-
|
|
3102
|
+
loadRecordField(ptr, t, inline) {
|
|
3103
|
+
if (inline) {
|
|
3104
|
+
const { tag, bits } = loadInlineUnion(this.B, ptr);
|
|
3105
|
+
const present = presentBits(this.B, tag, bits, undefinedArmTag(t, this.unionsById));
|
|
3106
|
+
return stackUnionBox(this.B, this.sizeType, tag, present);
|
|
3107
|
+
}
|
|
3108
|
+
const v = this.loadField(ptr, t, false);
|
|
3055
3109
|
if (t.kind !== "union" || undefinedArmTag(t, this.unionsById) < 0)
|
|
3056
3110
|
return v;
|
|
3057
3111
|
const absent = this.fieldAbsentTest(v, t.unionId);
|
|
@@ -3713,6 +3767,7 @@ export class LlEmitter {
|
|
|
3713
3767
|
case "searchParams":
|
|
3714
3768
|
case "stats":
|
|
3715
3769
|
case "fileHandle":
|
|
3770
|
+
case "dir":
|
|
3716
3771
|
case "spawnRes":
|
|
3717
3772
|
case "child":
|
|
3718
3773
|
case "childStream":
|
|
@@ -3755,7 +3810,7 @@ export class LlEmitter {
|
|
|
3755
3810
|
}
|
|
3756
3811
|
/** Guard for helpers that build or read a union's `%ScrUnion` box
|
|
3757
3812
|
* directly (library-shaped unions with fixed arms): a nullable union
|
|
3758
|
-
* reaching one is an emitter bug
|
|
3813
|
+
* reaching one is an emitter bug and throws InternalCompilerError. */
|
|
3759
3814
|
requireBoxedUnion(unionId) {
|
|
3760
3815
|
if (this.nullableUnions.has(unionId))
|
|
3761
3816
|
throw new InternalCompilerError(`llvm emitter bug: nullable union ${unionId} reached a tagged-box helper`);
|
|
@@ -3888,7 +3943,7 @@ export class LlEmitter {
|
|
|
3888
3943
|
const p = this.B.tmp();
|
|
3889
3944
|
this.B.line(`${p} = getelementptr inbounds %${classStructSym(className)}, ptr ${objName}, i64 0, i32 ${index}`);
|
|
3890
3945
|
this.markFieldPointer(p, field);
|
|
3891
|
-
return { ptr: p, type };
|
|
3946
|
+
return { ptr: p, type, inline: this.inlineUnions.classField(className, field) };
|
|
3892
3947
|
}
|
|
3893
3948
|
/** `o->vt->pre` — the dynamic class's preorder number (borrowed object;
|
|
3894
3949
|
* the static class names which struct spelling carries the vt word). */
|
|
@@ -3939,8 +3994,10 @@ export class LlEmitter {
|
|
|
3939
3994
|
if (index < 0)
|
|
3940
3995
|
throw new InternalCompilerError(`llvm emitter bug: missing union field ${field}`);
|
|
3941
3996
|
layout = "record:";
|
|
3942
|
-
for (let i = 0; i <= index; i++)
|
|
3943
|
-
|
|
3997
|
+
for (let i = 0; i <= index; i++) {
|
|
3998
|
+
const type = shape.fields[i].type;
|
|
3999
|
+
layout += `${llFieldType(type, this.inlineUnions.record(type))};`;
|
|
4000
|
+
}
|
|
3944
4001
|
}
|
|
3945
4002
|
const group = groups.get(layout);
|
|
3946
4003
|
if (group)
|
|
@@ -3952,7 +4009,13 @@ export class LlEmitter {
|
|
|
3952
4009
|
this.unionFieldReadGroups.set(key, result);
|
|
3953
4010
|
return result;
|
|
3954
4011
|
}
|
|
3955
|
-
/** The
|
|
4012
|
+
/** The zeroed `%ScrUnion` constant (inline-unions.ts unionBoxBits). */
|
|
4013
|
+
unionNoneRef() {
|
|
4014
|
+
this.needsUnionNone = true;
|
|
4015
|
+
return "@sc_union_none";
|
|
4016
|
+
}
|
|
4017
|
+
/** The field-slot pointer of a record member (rc header at index 0).
|
|
4018
|
+
* `inline`: the slot stores a scalar union's tag and bits. */
|
|
3956
4019
|
recordFieldPtr(objName, shapeId, field) {
|
|
3957
4020
|
const shape = this.recordShape(shapeId);
|
|
3958
4021
|
const idx = shape.fields.findIndex((f) => f.name === field);
|
|
@@ -3960,7 +4023,8 @@ export class LlEmitter {
|
|
|
3960
4023
|
throw new InternalCompilerError(`llvm emitter bug: unknown field ${field} on shape ${shapeId}`);
|
|
3961
4024
|
const p = this.B.tmp();
|
|
3962
4025
|
this.B.line(`${p} = getelementptr inbounds %${mangleRecordStruct(shapeId)}, ptr ${objName}, i64 0, i32 ${idx + 1}`);
|
|
3963
|
-
|
|
4026
|
+
const type = shape.fields[idx].type;
|
|
4027
|
+
return { ptr: p, type, inline: this.inlineUnions.record(type) };
|
|
3964
4028
|
}
|
|
3965
4029
|
/** The overflow map's slot pointer on an index-signature shape. */
|
|
3966
4030
|
recordOvfPtr(objName, shapeId) {
|
|
@@ -3973,10 +4037,16 @@ export class LlEmitter {
|
|
|
3973
4037
|
this.B.line(`${v} = load ptr, ptr ${p}`);
|
|
3974
4038
|
return v;
|
|
3975
4039
|
}
|
|
3976
|
-
/** Loads a record field (i8-stored bools trunc to i1).
|
|
3977
|
-
|
|
4040
|
+
/** Loads a record field (i8-stored bools trunc to i1). An inline union
|
|
4041
|
+
* field answers a private stack box with the slot's own bits, ABSENT
|
|
4042
|
+
* included: it may only be borrowed. */
|
|
4043
|
+
loadField(ptr, t, inline) {
|
|
3978
4044
|
const B = this.B;
|
|
3979
|
-
|
|
4045
|
+
if (inline) {
|
|
4046
|
+
const { tag, bits } = loadInlineUnion(B, ptr);
|
|
4047
|
+
return stackUnionBox(B, this.sizeType, tag, bits);
|
|
4048
|
+
}
|
|
4049
|
+
const fieldTy = llFieldType(t, false);
|
|
3980
4050
|
const raw = B.tmp();
|
|
3981
4051
|
B.line(`${raw} = load ${fieldTy}, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
3982
4052
|
if (fieldTy !== "i8")
|
|
@@ -3985,10 +4055,46 @@ export class LlEmitter {
|
|
|
3985
4055
|
B.line(`${b} = trunc i8 ${raw} to i1`);
|
|
3986
4056
|
return b;
|
|
3987
4057
|
}
|
|
3988
|
-
/**
|
|
3989
|
-
|
|
4058
|
+
/** A record field of this shape stores its scalar union inline. */
|
|
4059
|
+
recordFieldInline(shapeId, field) {
|
|
4060
|
+
const type = this.recordShape(shapeId).fields.find((f) => f.name === field)?.type;
|
|
4061
|
+
return type !== undefined && this.inlineUnions.record(type);
|
|
4062
|
+
}
|
|
4063
|
+
/** The value a field store writes: an inline union slot copies the tag
|
|
4064
|
+
* and bits of a borrowed projection, so no box is built for it. */
|
|
4065
|
+
emitFieldValue(value, inline) {
|
|
4066
|
+
return inline ? this.emitUnionProjection(value) : this.emitExpr(value);
|
|
4067
|
+
}
|
|
4068
|
+
/** Overwrites a field with `v` (from emitFieldValue). A reference moves
|
|
4069
|
+
* in, and the old value is released AFTER the field is overwritten. */
|
|
4070
|
+
replaceField(ptr, type, inline, v) {
|
|
4071
|
+
if (!inline && isRefCounted(type)) {
|
|
4072
|
+
this.moveTemp(v);
|
|
4073
|
+
const old = this.B.tmp();
|
|
4074
|
+
this.B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
4075
|
+
this.storeField(ptr, type, v.name, false);
|
|
4076
|
+
this.releaseValue(old, type);
|
|
4077
|
+
return;
|
|
4078
|
+
}
|
|
4079
|
+
this.storeField(ptr, type, v.name, inline);
|
|
4080
|
+
}
|
|
4081
|
+
/** Stores `v` (from emitFieldValue) into a fresh field slot. */
|
|
4082
|
+
initField(ptr, type, inline, v) {
|
|
4083
|
+
if (!inline && isRefCounted(type))
|
|
4084
|
+
this.moveTemp(v);
|
|
4085
|
+
this.storeField(ptr, type, v.name, inline);
|
|
4086
|
+
}
|
|
4087
|
+
/** Stores a record field (i1 zext to the i8 storage). An inline union
|
|
4088
|
+
* field copies the tag and bits of the union value, which its owner
|
|
4089
|
+
* keeps. */
|
|
4090
|
+
storeField(ptr, t, value, inline) {
|
|
3990
4091
|
const B = this.B;
|
|
3991
|
-
|
|
4092
|
+
if (inline) {
|
|
4093
|
+
const { tag, bits } = unionBoxBits(B, value, this.unionNoneRef());
|
|
4094
|
+
storeInlineUnion(B, ptr, tag, bits);
|
|
4095
|
+
return;
|
|
4096
|
+
}
|
|
4097
|
+
const fieldTy = llFieldType(t, false);
|
|
3992
4098
|
if (fieldTy !== "i8") {
|
|
3993
4099
|
B.line(`store ${fieldTy} ${value}, ptr ${ptr}${this.fieldAliasAttachment(ptr)}`);
|
|
3994
4100
|
return;
|
|
@@ -4458,7 +4564,7 @@ export class LlEmitter {
|
|
|
4458
4564
|
this.integerArrayBindings.clear();
|
|
4459
4565
|
this.loopArrayBorrows =
|
|
4460
4566
|
this.debug === null
|
|
4461
|
-
? findLoopArrayBorrows(fn, this.callLifetimes, this.referenceEffects, this.optionalArrayReads, this.referenceWrites)
|
|
4567
|
+
? findLoopArrayBorrows(fn, this.callLifetimes, this.referenceEffects, this.optionalArrayReads, this.referenceWrites, this.fnByName)
|
|
4462
4568
|
: new Set();
|
|
4463
4569
|
this.localArrayReads = findLocalArrayReads(fn, this.fnByName, this.unionsById, this.referenceEffects.functions, this.callLifetimes, this.optionalArrayReads, this.loopArrayBorrows, this.debug === null ? this.referenceEffects : undefined);
|
|
4464
4570
|
this.callArrayReads = findCallArrayReads(fn, this.optionalArrayReads, this.referenceEffects.functions, this.callLifetimes, this.debug === null ? this.referenceEffects : undefined);
|
|
@@ -4775,6 +4881,15 @@ export class LlEmitter {
|
|
|
4775
4881
|
// a call, and an integer index converts to a double and back across it.
|
|
4776
4882
|
if (fn.name.startsWith("%arr.idxOr."))
|
|
4777
4883
|
attrs = `inlinehint ${attrs}`;
|
|
4884
|
+
// Interface dispatch is a few key tests and direct calls ahead of the
|
|
4885
|
+
// checked dynamic call. Keeping that fallback out of line leaves the
|
|
4886
|
+
// tests small enough to inline at each call site.
|
|
4887
|
+
if (fn.name.startsWith("%dyn.class.protocol.fallback."))
|
|
4888
|
+
attrs = `noinline ${attrs}`;
|
|
4889
|
+
else if (fn.name.startsWith("%dyn.class.protocol."))
|
|
4890
|
+
attrs = `inlinehint ${attrs}`;
|
|
4891
|
+
if (fn.name.startsWith(RESULT_ENTRY_PREFIX))
|
|
4892
|
+
attrs = `inlinehint ${attrs}`;
|
|
4778
4893
|
const debug = this.debugScope === null ? "" : ` !dbg ${this.debugScope}`;
|
|
4779
4894
|
const symbol = borrowed ? mangleBorrowedFunction(fn.name) : mangleFunction(fn.name);
|
|
4780
4895
|
let body = `define internal ${ret} @${symbol}${int32Abi ? INT32_ABI_SUFFIX : ""}(${params.join(", ")}) ${attrs}${debug} { ; ${fn.name}\n${B.render()}\n}`;
|
|
@@ -4861,11 +4976,23 @@ export class LlEmitter {
|
|
|
4861
4976
|
* exception dummy (tag -1) answers NULL. */
|
|
4862
4977
|
boxScalarUnion(pair, type) {
|
|
4863
4978
|
const B = this.B;
|
|
4864
|
-
const unionId = type.kind === "union" ? type.unionId : "";
|
|
4865
|
-
const arms = this.unionsById.get(unionId).arms;
|
|
4866
4979
|
const tag = B.tmp(), bits = B.tmp();
|
|
4867
4980
|
B.line(`${tag} = extractvalue ${SCALAR_UNION_RESULT} ${pair}, 0`);
|
|
4868
4981
|
B.line(`${bits} = extractvalue ${SCALAR_UNION_RESULT} ${pair}, 1`);
|
|
4982
|
+
return this.boxScalarUnionBits(tag, bits, type);
|
|
4983
|
+
}
|
|
4984
|
+
/** A fresh heap box (+1) for an inline union field's value; the ABSENT
|
|
4985
|
+
* state reads as the undefined arm. */
|
|
4986
|
+
inlineFieldUnion(ptr, type) {
|
|
4987
|
+
const { tag, bits } = loadInlineUnion(this.B, ptr);
|
|
4988
|
+
return this.boxScalarUnionBits(tag, bits, type);
|
|
4989
|
+
}
|
|
4990
|
+
/** boxScalarUnion over a separate tag and payload bits. Unit arms answer
|
|
4991
|
+
* their immortal instances whatever the bits. */
|
|
4992
|
+
boxScalarUnionBits(tag, bits, type) {
|
|
4993
|
+
const B = this.B;
|
|
4994
|
+
const unionId = type.kind === "union" ? type.unionId : "";
|
|
4995
|
+
const arms = this.unionsById.get(unionId).arms;
|
|
4869
4996
|
const join = B.newLabel("union.box.join"), none = B.newLabel("union.box.none");
|
|
4870
4997
|
const labels = arms.map(() => B.newLabel("union.box.arm"));
|
|
4871
4998
|
B.terminate(`switch i32 ${tag}, label %${none} [ ${labels.map((label, armTag) => `i32 ${armTag}, label %${label}`).join(" ")} ]`);
|
|
@@ -4972,6 +5099,12 @@ export class LlEmitter {
|
|
|
4972
5099
|
canBorrowCallArgument(value) {
|
|
4973
5100
|
if (value.kind === "strLit")
|
|
4974
5101
|
return true;
|
|
5102
|
+
// An exact capsule owns its instance while the capsule's binding holds it.
|
|
5103
|
+
if (value.kind === "dynCheck" && value.exact)
|
|
5104
|
+
return value.value.kind === "varRef" && this.canBorrowCallArgument(value.value);
|
|
5105
|
+
// An inline union field has no box to lend.
|
|
5106
|
+
if (this.inlineFieldGet(value))
|
|
5107
|
+
return false;
|
|
4975
5108
|
// Class casts reinterpret the same pointer (prefix layouts).
|
|
4976
5109
|
if ((value.kind === "upcast" || value.kind === "downcast") &&
|
|
4977
5110
|
value.value.type.kind === "object")
|
|
@@ -5484,6 +5617,24 @@ export class LlEmitter {
|
|
|
5484
5617
|
emitBorrowedArrayRead(this, s.init, b.slot);
|
|
5485
5618
|
break;
|
|
5486
5619
|
}
|
|
5620
|
+
const holeRead = this.loopArrayBorrows.has(s) ? dynHoleRead(s.init) : null;
|
|
5621
|
+
if (holeRead && s.init.kind === "ternary") {
|
|
5622
|
+
// A hole reads as the immortal undefined value, which needs no owner.
|
|
5623
|
+
const present = this.emitExpr(s.init.cond);
|
|
5624
|
+
const filled = B.newLabel("borrow.hole.filled"), missing = B.newLabel("borrow.hole.missing"), done = B.newLabel("borrow.hole.done");
|
|
5625
|
+
B.condBr(present.name, filled, missing);
|
|
5626
|
+
B.startBlock(filled);
|
|
5627
|
+
emitBorrowedArrayRead(this, holeRead, b.slot);
|
|
5628
|
+
B.br(done);
|
|
5629
|
+
B.startBlock(missing);
|
|
5630
|
+
this.declare("declare ptr @scr_dyn_undefined()");
|
|
5631
|
+
const undef = B.tmp();
|
|
5632
|
+
B.line(`${undef} = call ptr @scr_dyn_undefined()`);
|
|
5633
|
+
B.line(`store ptr ${undef}, ptr ${b.slot}`);
|
|
5634
|
+
B.br(done);
|
|
5635
|
+
B.startBlock(done);
|
|
5636
|
+
break;
|
|
5637
|
+
}
|
|
5487
5638
|
// A stable lexical alias cannot outlive its unchanged local owner.
|
|
5488
5639
|
// Whole-value uses still retain their own copies, so returning or
|
|
5489
5640
|
// storing the alias preserves the ordinary heap representation.
|
|
@@ -5542,10 +5693,9 @@ export class LlEmitter {
|
|
|
5542
5693
|
storeLocalUnion(this, localStorage, s.value);
|
|
5543
5694
|
break;
|
|
5544
5695
|
}
|
|
5545
|
-
const
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
this.emitStringSelfConcatAssign(s.localId, concat.left, suffix, false);
|
|
5696
|
+
const self = matchStringSelfConcat(s.localId, s.value);
|
|
5697
|
+
if (self) {
|
|
5698
|
+
this.emitStringSelfConcatAssign(s.localId, self.left, self.suffix, false);
|
|
5549
5699
|
break;
|
|
5550
5700
|
}
|
|
5551
5701
|
const b = this.binding(s.localId);
|
|
@@ -5710,24 +5860,17 @@ export class LlEmitter {
|
|
|
5710
5860
|
break;
|
|
5711
5861
|
}
|
|
5712
5862
|
const obj = this.emitStableReceiver(s.obj, [s.value]);
|
|
5713
|
-
const v = this.
|
|
5863
|
+
const v = this.emitFieldValue(s.value, s.kind === "recordSet"
|
|
5864
|
+
? this.recordFieldInline(s.shapeId, s.field)
|
|
5865
|
+
: this.inlineUnions.classField(s.className, s.field));
|
|
5714
5866
|
if (s.kind === "fieldSet")
|
|
5715
5867
|
this.emitStoreGuard(obj.name, s);
|
|
5716
5868
|
else if (this.publishedTypes?.recordGuarded(s.shapeId) === true)
|
|
5717
5869
|
this.emitPublishedFieldGuard(obj.name, null, s.field);
|
|
5718
|
-
const { ptr, type } = s.kind === "fieldSet"
|
|
5870
|
+
const { ptr, type, inline } = s.kind === "fieldSet"
|
|
5719
5871
|
? this.classFieldPtr(obj.name, s.className, s.field)
|
|
5720
5872
|
: 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
|
-
}
|
|
5873
|
+
this.replaceField(ptr, type, inline, v);
|
|
5731
5874
|
if (s.kind === "fieldSet" &&
|
|
5732
5875
|
s.field === "name" &&
|
|
5733
5876
|
this.classMeta.get(s.className)?.root.def.name === "%Error") {
|
|
@@ -5828,15 +5971,20 @@ export class LlEmitter {
|
|
|
5828
5971
|
const lw = B.newLabel("rks.w");
|
|
5829
5972
|
B.condBr(pend, join, lw);
|
|
5830
5973
|
B.startBlock(lw);
|
|
5831
|
-
const { ptr, type } = this.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
5832
|
-
if (
|
|
5974
|
+
const { ptr, type, inline } = this.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
5975
|
+
if (inline) {
|
|
5976
|
+
// The slot copies the checked value's bits; nv is released below.
|
|
5977
|
+
this.storeField(ptr, type, nv, true);
|
|
5978
|
+
this.releaseValue(nv, type);
|
|
5979
|
+
}
|
|
5980
|
+
else if (isRefCounted(type)) {
|
|
5833
5981
|
const old = B.tmp();
|
|
5834
5982
|
B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
5835
|
-
this.storeField(ptr, type, nv);
|
|
5983
|
+
this.storeField(ptr, type, nv, false);
|
|
5836
5984
|
this.releaseValue(old, type);
|
|
5837
5985
|
}
|
|
5838
5986
|
else {
|
|
5839
|
-
this.storeField(ptr, type, nv);
|
|
5987
|
+
this.storeField(ptr, type, nv, false);
|
|
5840
5988
|
}
|
|
5841
5989
|
B.br(join);
|
|
5842
5990
|
B.startBlock(ln);
|
|
@@ -5859,15 +6007,20 @@ export class LlEmitter {
|
|
|
5859
6007
|
const ln = B.newLabel("rks.n");
|
|
5860
6008
|
B.condBr(hit, lh, ln);
|
|
5861
6009
|
B.startBlock(lh);
|
|
5862
|
-
const { ptr, type } = this.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
5863
|
-
if (
|
|
6010
|
+
const { ptr, type, inline } = this.recordFieldPtr(obj.name, s.shapeId, f.name);
|
|
6011
|
+
if (inline) {
|
|
6012
|
+
// The write owns the moved-in value; the slot copies its bits.
|
|
6013
|
+
this.storeField(ptr, type, v.name, true);
|
|
6014
|
+
this.releaseValue(v.name, type);
|
|
6015
|
+
}
|
|
6016
|
+
else if (isRefCounted(type)) {
|
|
5864
6017
|
const old = B.tmp();
|
|
5865
6018
|
B.line(`${old} = load ptr, ptr ${ptr}`);
|
|
5866
|
-
this.storeField(ptr, type, v.name);
|
|
6019
|
+
this.storeField(ptr, type, v.name, false);
|
|
5867
6020
|
this.releaseValue(old, type);
|
|
5868
6021
|
}
|
|
5869
6022
|
else {
|
|
5870
|
-
this.storeField(ptr, type, v.name);
|
|
6023
|
+
this.storeField(ptr, type, v.name, false);
|
|
5871
6024
|
}
|
|
5872
6025
|
B.br(join);
|
|
5873
6026
|
B.startBlock(ln);
|
|
@@ -6528,7 +6681,7 @@ export class LlEmitter {
|
|
|
6528
6681
|
break;
|
|
6529
6682
|
default: {
|
|
6530
6683
|
// Statement coverage is now total (bytesSet closed the set) —
|
|
6531
|
-
// keep
|
|
6684
|
+
// keep throwing LlvmUnsupportedError for any future IR statement kind.
|
|
6532
6685
|
const rest = s;
|
|
6533
6686
|
const k = rest.kind;
|
|
6534
6687
|
throw new LlvmUnsupportedError(`stmt:${k}`, rest.loc);
|
|
@@ -6874,7 +7027,11 @@ export class LlEmitter {
|
|
|
6874
7027
|
if (e.kind === "seqExpr" &&
|
|
6875
7028
|
isRefCounted(e.result.type) &&
|
|
6876
7029
|
e.result.kind !== "strLit" &&
|
|
6877
|
-
this.discardableRead(e.result)
|
|
7030
|
+
(this.discardableRead(e.result) ||
|
|
7031
|
+
// A function-local binding's read has no effect of its own (a
|
|
7032
|
+
// compound assignment's result, say); a module binding's read may
|
|
7033
|
+
// throw before initialization, so it stays.
|
|
7034
|
+
(e.result.kind === "varRef" && this.binding(e.result.localId).kind === "local"))) {
|
|
6878
7035
|
this.emitSequence(() => {
|
|
6879
7036
|
for (const s of e.stmts)
|
|
6880
7037
|
this.emitStmt(s);
|
|
@@ -6905,8 +7062,11 @@ export class LlEmitter {
|
|
|
6905
7062
|
// of first building the suffix as a separate string.
|
|
6906
7063
|
const parts = stringParts(suffix);
|
|
6907
7064
|
const mixed = parts.length > 1 || numberPart(parts[0]) !== null;
|
|
7065
|
+
const charCode = mixed ? null : this.emitSingleCharCode(suffix);
|
|
6908
7066
|
const inputs = mixed ? emitConcatInputs(this, parts) : [];
|
|
6909
|
-
|
|
7067
|
+
// The concat only reads the suffix; relinquishing the binding below
|
|
7068
|
+
// runs no code that could rebind a borrowed local.
|
|
7069
|
+
const right = mixed || charCode !== null ? null : emitStringInputs(this, [suffix])[0];
|
|
6910
7070
|
const b = this.binding(localId);
|
|
6911
7071
|
const B = this.B;
|
|
6912
7072
|
if (b.kind === "boxed") {
|
|
@@ -6920,7 +7080,14 @@ export class LlEmitter {
|
|
|
6920
7080
|
this.releaseValue(old, b.type);
|
|
6921
7081
|
}
|
|
6922
7082
|
let raw;
|
|
6923
|
-
if (
|
|
7083
|
+
if (charCode !== null) {
|
|
7084
|
+
// The snapshot moves into the consuming character append.
|
|
7085
|
+
this.moveTemp(snapshot);
|
|
7086
|
+
this.declare(`declare ptr @scr_str_concat_move_char_code(ptr, double)`);
|
|
7087
|
+
raw = B.tmp();
|
|
7088
|
+
B.line(`${raw} = call ptr @scr_str_concat_move_char_code(ptr ${snapshot.name}, double ${charCode.name})`);
|
|
7089
|
+
}
|
|
7090
|
+
else if (right === null) {
|
|
6924
7091
|
raw = emitMixedConcat(this, snapshot.name, inputs);
|
|
6925
7092
|
}
|
|
6926
7093
|
else {
|
|
@@ -6945,6 +7112,17 @@ export class LlEmitter {
|
|
|
6945
7112
|
}
|
|
6946
7113
|
return result;
|
|
6947
7114
|
}
|
|
7115
|
+
/** The code of a one-argument `String.fromCharCode(c)` suffix, emitted, so
|
|
7116
|
+
* `s += String.fromCharCode(c)` appends the character without building
|
|
7117
|
+
* the one-character string; null for any other suffix. */
|
|
7118
|
+
emitSingleCharCode(suffix) {
|
|
7119
|
+
if (suffix.kind !== "libCall" || suffix.fn !== "string.fromCharCode")
|
|
7120
|
+
return null;
|
|
7121
|
+
const packed = suffix.args[0];
|
|
7122
|
+
if (packed?.kind !== "arrayLit" || packed.elems.length !== 1 || packed.spreads?.length)
|
|
7123
|
+
return null;
|
|
7124
|
+
return this.emitExpr(packed.elems[0]);
|
|
7125
|
+
}
|
|
6948
7126
|
/** `local = local + suffix` when the suffix cannot read or write the
|
|
6949
7127
|
* local (an unboxed binding is only reachable through this function's own
|
|
6950
7128
|
* expressions): reading the binding after the suffix gives the value the
|
|
@@ -6964,14 +7142,21 @@ export class LlEmitter {
|
|
|
6964
7142
|
return null;
|
|
6965
7143
|
const parts = stringParts(suffix);
|
|
6966
7144
|
const mixed = parts.length > 1 || numberPart(parts[0]) !== null;
|
|
7145
|
+
const charCode = mixed ? null : this.emitSingleCharCode(suffix);
|
|
6967
7146
|
const inputs = mixed ? emitConcatInputs(this, parts) : [];
|
|
6968
|
-
|
|
7147
|
+
// The concat only reads the suffix, which may stay borrowed.
|
|
7148
|
+
const right = mixed || charCode !== null ? null : emitStringInputs(this, [suffix])[0];
|
|
6969
7149
|
this.materializeSplitLocal(localId);
|
|
6970
7150
|
const B = this.B;
|
|
6971
7151
|
const head = B.tmp();
|
|
6972
7152
|
B.line(`${head} = load ptr, ptr ${b.slot}`);
|
|
6973
7153
|
let raw;
|
|
6974
|
-
if (
|
|
7154
|
+
if (charCode !== null) {
|
|
7155
|
+
this.declare(`declare ptr @scr_str_concat_move_char_code(ptr, double)`);
|
|
7156
|
+
raw = B.tmp();
|
|
7157
|
+
B.line(`${raw} = call ptr @scr_str_concat_move_char_code(ptr ${head}, double ${charCode.name})`);
|
|
7158
|
+
}
|
|
7159
|
+
else if (right === null) {
|
|
6975
7160
|
raw = emitMixedConcat(this, head, inputs, true);
|
|
6976
7161
|
}
|
|
6977
7162
|
else {
|
|
@@ -7054,6 +7239,7 @@ export class LlEmitter {
|
|
|
7054
7239
|
tracedShapes: this.tracedShapes,
|
|
7055
7240
|
unionsById: this.unionsById,
|
|
7056
7241
|
recordsById: this.recordsById,
|
|
7242
|
+
inlineUnions: this.inlineUnions,
|
|
7057
7243
|
nullableArm: (t) => this.nullableUnions.of(t)?.arm ?? null,
|
|
7058
7244
|
classInfo: (className) => {
|
|
7059
7245
|
const meta = this.classMetaOf(className);
|
|
@@ -7063,11 +7249,16 @@ export class LlEmitter {
|
|
|
7063
7249
|
pre: meta.pre,
|
|
7064
7250
|
post: meta.post,
|
|
7065
7251
|
runtimeRooted: meta.root.def.runtime === true,
|
|
7066
|
-
fields:
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7252
|
+
// Inline scalar-union fields are plain bits: nothing to push.
|
|
7253
|
+
fields: meta.def.fields.flatMap((f) => this.inlineUnions.classField(className, f.name)
|
|
7254
|
+
? []
|
|
7255
|
+
: [
|
|
7256
|
+
{
|
|
7257
|
+
name: f.name,
|
|
7258
|
+
index: classFieldIndex(meta, f.name).index,
|
|
7259
|
+
type: this.nullableFields.storageType(className, f.name, f.type),
|
|
7260
|
+
},
|
|
7261
|
+
]),
|
|
7071
7262
|
};
|
|
7072
7263
|
},
|
|
7073
7264
|
classesInInterval: (pre, post) => byPre.filter((m) => m.pre >= pre && m.pre <= post).map((m) => m.def.name),
|
|
@@ -7234,6 +7425,8 @@ export class LlEmitter {
|
|
|
7234
7425
|
this.B.line(`${value} = load ptr, ptr ${binding.slot}`);
|
|
7235
7426
|
return { name: value, type: e.type };
|
|
7236
7427
|
}
|
|
7428
|
+
if (e.kind === "dynCheck" && e.exact)
|
|
7429
|
+
return this.emitExactCapsuleObject(e.value, e.type);
|
|
7237
7430
|
if (e.kind === "chainRecv") {
|
|
7238
7431
|
// The chain's bind slot holds its receiver unchanged until the body
|
|
7239
7432
|
// finishes, owned by the slot itself or by the chain's receiver.
|
|
@@ -7294,13 +7487,14 @@ export class LlEmitter {
|
|
|
7294
7487
|
if (e.kind === "recordGet" || e.kind === "fieldGet") {
|
|
7295
7488
|
const receiver = this.emitReadReceiver(e.obj);
|
|
7296
7489
|
if (e.kind === "recordGet") {
|
|
7297
|
-
|
|
7298
|
-
|
|
7490
|
+
// An inline union field answers a private stack box.
|
|
7491
|
+
const { ptr, type, inline } = this.recordFieldPtr(receiver.name, e.shapeId, e.field);
|
|
7492
|
+
return { name: this.loadRecordField(ptr, type, inline), type: e.type };
|
|
7299
7493
|
}
|
|
7300
|
-
const { ptr, type } = this.classFieldPtr(receiver.name, e.className, e.field);
|
|
7494
|
+
const { ptr, type, inline } = this.classFieldPtr(receiver.name, e.className, e.field);
|
|
7301
7495
|
if (this.int32Slots.isField(e.className, e.field))
|
|
7302
7496
|
return this.loadInt32Field(ptr, e.type);
|
|
7303
|
-
return { name: this.loadField(ptr, type), type: e.type };
|
|
7497
|
+
return { name: this.loadField(ptr, type, inline), type: e.type };
|
|
7304
7498
|
}
|
|
7305
7499
|
if (e.kind === "ternary" && this.canBorrowReceiver(e.then) && this.canBorrowReceiver(e.else_)) {
|
|
7306
7500
|
// Checked projections lower to a ternary with an always-throwing
|
|
@@ -7364,7 +7558,15 @@ export class LlEmitter {
|
|
|
7364
7558
|
matchMapRead(e, this.boxedUnionsById) !== null ||
|
|
7365
7559
|
this.optionalArrayReads.get(e) !== null ||
|
|
7366
7560
|
isScalarOptionalSource(e, this.unionSources) ||
|
|
7367
|
-
this.scalarResultCall(e)
|
|
7561
|
+
this.scalarResultCall(e) ||
|
|
7562
|
+
this.inlineFieldGet(e));
|
|
7563
|
+
}
|
|
7564
|
+
/** A read of a record or class field that stores its scalar union
|
|
7565
|
+
* inline. */
|
|
7566
|
+
inlineFieldGet(e) {
|
|
7567
|
+
if (e.kind === "recordGet")
|
|
7568
|
+
return this.recordFieldInline(e.shapeId, e.field);
|
|
7569
|
+
return e.kind === "fieldGet" && this.inlineUnions.classField(e.className, e.field);
|
|
7368
7570
|
}
|
|
7369
7571
|
/** The nullable-pointer representation behind a union-typed class field
|
|
7370
7572
|
* read, or null for every other expression. */
|
|
@@ -7503,6 +7705,15 @@ export class LlEmitter {
|
|
|
7503
7705
|
this.localArrayReads.has(localId) ||
|
|
7504
7706
|
this.mapReadLifetimes.locals.has(localId));
|
|
7505
7707
|
}
|
|
7708
|
+
/** The instance of a capsule known to hold exactly this class (borrowed). */
|
|
7709
|
+
emitExactCapsuleObject(value, type) {
|
|
7710
|
+
const capsule = this.emitReadReceiver(value);
|
|
7711
|
+
const slot = this.B.tmp();
|
|
7712
|
+
const object = this.B.tmp();
|
|
7713
|
+
this.B.line(`${slot} = getelementptr inbounds i8, ptr ${capsule.name}, i64 16 ; ->v.typed_ref.ptr`);
|
|
7714
|
+
this.B.line(`${object} = load ptr, ptr ${slot}`);
|
|
7715
|
+
return { name: object, type };
|
|
7716
|
+
}
|
|
7506
7717
|
canBorrowReceiver(e) {
|
|
7507
7718
|
switch (e.kind) {
|
|
7508
7719
|
case "chainRecv":
|
|
@@ -7520,9 +7731,11 @@ export class LlEmitter {
|
|
|
7520
7731
|
case "downcast":
|
|
7521
7732
|
case "upcast":
|
|
7522
7733
|
return this.canBorrowReceiver(e.value);
|
|
7734
|
+
// An inline union field has no box to lend: projections read it
|
|
7735
|
+
// through emitReadReceiver's private stack box.
|
|
7523
7736
|
case "fieldGet":
|
|
7524
7737
|
case "recordGet":
|
|
7525
|
-
return this.canBorrowReceiver(e.obj);
|
|
7738
|
+
return !this.inlineFieldGet(e) && this.canBorrowReceiver(e.obj);
|
|
7526
7739
|
case "ternary":
|
|
7527
7740
|
return this.canBorrowReceiver(e.then) && this.canBorrowReceiver(e.else_);
|
|
7528
7741
|
case "seqExpr": {
|
|
@@ -7758,8 +7971,11 @@ export class LlEmitter {
|
|
|
7758
7971
|
fsRenameThunkFor(cbT) {
|
|
7759
7972
|
return fsRenameThunkFor(this, cbT);
|
|
7760
7973
|
}
|
|
7761
|
-
cryptoBytesThunkFor(cbT, arrayBuffer = false) {
|
|
7762
|
-
return cryptoBytesThunkFor(this, cbT, arrayBuffer);
|
|
7974
|
+
cryptoBytesThunkFor(cbT, arrayBuffer = false, valueMode = "buffer") {
|
|
7975
|
+
return cryptoBytesThunkFor(this, cbT, arrayBuffer, valueMode);
|
|
7976
|
+
}
|
|
7977
|
+
cryptoIntThunkFor(cbT) {
|
|
7978
|
+
return cryptoIntThunkFor(this, cbT);
|
|
7763
7979
|
}
|
|
7764
7980
|
zlibBytesThunkFor(cbT) {
|
|
7765
7981
|
return zlibBytesThunkFor(this, cbT);
|