@yabgu_gm/tensionscript 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/asc.generated.d.ts +378 -17
- package/dist/asc.js +1 -1
- package/dist/asc.js.map +1 -1
- package/dist/assemblyscript.generated.d.ts +378 -17
- package/dist/assemblyscript.js +151 -151
- package/dist/assemblyscript.js.map +3 -3
- package/dist/importmap.json +2 -2
- package/dist/web.js +3 -3
- package/package.json +1 -1
|
@@ -2414,6 +2414,23 @@ declare module "types:tensionscript/src/types" {
|
|
|
2414
2414
|
fixedElementType: Type | null;
|
|
2415
2415
|
/** Element count of a {@link TypeKind.FixedArray}, else `0`. */
|
|
2416
2416
|
fixedLength: number;
|
|
2417
|
+
/**
|
|
2418
|
+
* Who owns a {@link TypeKind.FixedArray}'s storage — the second axis of the
|
|
2419
|
+
* kind, alongside the element and the length.
|
|
2420
|
+
*
|
|
2421
|
+
* The memory model was already on the AST (`TypeNode.memoryModel`) and was
|
|
2422
|
+
* simply dropped before Landing 5a.5: `Type.fixedArray` interned one object
|
|
2423
|
+
* per `(element, length)`, so `[u32 * 4]`, `@unmanaged [u32 * 4]`,
|
|
2424
|
+
* `@managed [u32 * 4]` and `@inline [u32 * 4]` were **the same Type**, and
|
|
2425
|
+
* the prefix was decorative — measured, all four emitted identical code.
|
|
2426
|
+
*
|
|
2427
|
+
* The two forms are not the same thing. `[u32 * 4]` is 16 bytes of inline
|
|
2428
|
+
* elements with no address of its own; `@unmanaged [u32 * 4]` is a pointer to
|
|
2429
|
+
* four elements, i.e. 4 bytes. Part of {@link equals} for the same reason
|
|
2430
|
+
* {@link dynamicMemoryModel} is: interning them together would make the two
|
|
2431
|
+
* spellings the same object, and no downstream test could tell them apart.
|
|
2432
|
+
*/
|
|
2433
|
+
fixedMemoryModel: MemoryModelCode;
|
|
2417
2434
|
/**
|
|
2418
2435
|
* Element type of a {@link TypeKind.UnmanagedArray}, else `null`.
|
|
2419
2436
|
*
|
|
@@ -2437,12 +2454,16 @@ declare module "types:tensionscript/src/types" {
|
|
|
2437
2454
|
*/
|
|
2438
2455
|
dynamicMemoryModel: MemoryModelCode;
|
|
2439
2456
|
/**
|
|
2440
|
-
* Alignment (log2) of a {@link TypeKind.FixedArray}
|
|
2457
|
+
* Alignment (log2) of a {@link TypeKind.FixedArray}.
|
|
2458
|
+
*
|
|
2459
|
+
* For the **value** form this is the element's. `alignLog2` cannot derive
|
|
2460
|
+
* that from `byteSize` -- a 24-byte `f32[6]` would report 16-byte alignment
|
|
2461
|
+
* (`31 - clz(24)` = 4), and a 96-byte `f32[24]` would report 64. An array is
|
|
2462
|
+
* aligned as its element is, no matter how long it is, so the value is carried
|
|
2463
|
+
* rather than computed.
|
|
2441
2464
|
*
|
|
2442
|
-
*
|
|
2443
|
-
*
|
|
2444
|
-
* report 64. An array is aligned as its element is, no matter how long it is,
|
|
2445
|
-
* so the value is carried rather than computed.
|
|
2465
|
+
* For the **view** form it is the *pointer's*, because that is what the value
|
|
2466
|
+
* is: the extent says nothing about how the address is aligned.
|
|
2446
2467
|
*/
|
|
2447
2468
|
private fixedAlignLog2;
|
|
2448
2469
|
/** Respective non-nullable type, if nullable. */
|
|
@@ -2518,6 +2539,34 @@ declare module "types:tensionscript/src/types" {
|
|
|
2518
2539
|
get isManaged(): boolean;
|
|
2519
2540
|
/** Tests if this is a class type explicitly annotated as unmanaged. */
|
|
2520
2541
|
get isUnmanaged(): boolean;
|
|
2542
|
+
/**
|
|
2543
|
+
* This type's extent in bytes when it is stored **inline**, rather than by
|
|
2544
|
+
* reference.
|
|
2545
|
+
*
|
|
2546
|
+
* For a scalar the two are the same number, and for an ordinary class neither
|
|
2547
|
+
* is what an inline array wants -- a class element is stored as its 4-byte
|
|
2548
|
+
* reference, so `byteSize` is right there. The one case where `byteSize` is
|
|
2549
|
+
* **wrong** is a C-layout record (`@unmanaged` / `@managed struct`, and
|
|
2550
|
+
* `@inline struct`, which the parser also flags `@unmanaged`): there
|
|
2551
|
+
* `byteSize` is the reference width (4) while the bytes an inline element
|
|
2552
|
+
* actually occupies are the record's layout size, `Class#nextMemoryOffset`.
|
|
2553
|
+
*
|
|
2554
|
+
* That is the same pair `builtin_sizeof` distinguishes
|
|
2555
|
+
* (`builtins.ts`, the `Unmanaged | ManagedStruct` branch), and it is why
|
|
2556
|
+
* `sizeof<Props>()` answered 16 while `sizeof<[Props * 4]>()` answered 16
|
|
2557
|
+
* instead of 64: the array's size was built from the reference width.
|
|
2558
|
+
*/
|
|
2559
|
+
get inlineExtentBytes(): number;
|
|
2560
|
+
/**
|
|
2561
|
+
* This type's alignment as a log2 when it is stored inline.
|
|
2562
|
+
*
|
|
2563
|
+
* A record's alignment is the strongest of its fields', accumulated while the
|
|
2564
|
+
* resolver lays it out (`Class#alignLog2`), and **not** `Type#alignLog2` —
|
|
2565
|
+
* which reads the class's 4-byte reference size and would report 2 for every
|
|
2566
|
+
* record, including one aligned to 8. The same distinction `builtin_alignof`
|
|
2567
|
+
* makes, for the same reason.
|
|
2568
|
+
*/
|
|
2569
|
+
get inlineAlignLog2(): number;
|
|
2521
2570
|
get isMemory(): boolean;
|
|
2522
2571
|
/** Gets the corresponding non-nullable type. */
|
|
2523
2572
|
get nonNullableType(): Type;
|
|
@@ -2592,19 +2641,39 @@ declare module "types:tensionscript/src/types" {
|
|
|
2592
2641
|
/** A 32-bit float. */
|
|
2593
2642
|
static readonly f32: Type;
|
|
2594
2643
|
/** A 64-bit float. */
|
|
2595
|
-
/** Interned fixed-array types, keyed by element type and length. */
|
|
2644
|
+
/** Interned fixed-array types, keyed by model, element type and length. */
|
|
2596
2645
|
private static _fixedArrays;
|
|
2597
2646
|
/**
|
|
2598
|
-
* Gets the {@link TypeKind.FixedArray} of `elementType` repeated `length`
|
|
2647
|
+
* Gets the {@link TypeKind.FixedArray} of `elementType` repeated `length`
|
|
2648
|
+
* times, in the storage named by `memoryModel`.
|
|
2649
|
+
*
|
|
2650
|
+
* Interned: the same `(model, element, length)` always yields the same `Type`,
|
|
2651
|
+
* so `offsetof`, `alignof`, `sizeof` and field lookup can compare by identity
|
|
2652
|
+
* the way they do for every other type.
|
|
2653
|
+
*
|
|
2654
|
+
* **The model is part of the identity**, and that is the point of Landing
|
|
2655
|
+
* 5a.5. Before it, this function had one axis (element, length) and the memory
|
|
2656
|
+
* model was dropped, so `[u32 * 4]` and `@unmanaged [u32 * 4]` were the same
|
|
2657
|
+
* Type object — measured: both compiled, both `sizeof` 16, and all four
|
|
2658
|
+
* spellings (`[T * N]`, `@unmanaged [T * N]`, `@managed [T * N]`,
|
|
2659
|
+
* `@inline [T * N]`) emitted byte-identical code. A prefix that changes
|
|
2660
|
+
* nothing is worse than one that is refused, because it reads as if it means
|
|
2661
|
+
* something.
|
|
2599
2662
|
*
|
|
2600
|
-
*
|
|
2601
|
-
*
|
|
2602
|
-
*
|
|
2603
|
-
*
|
|
2604
|
-
*
|
|
2605
|
-
* is
|
|
2663
|
+
* The two honourable forms differ in both size and alignment:
|
|
2664
|
+
*
|
|
2665
|
+
* value (`Any` / `Inline`) — inline elements: `elementSize * length` bytes,
|
|
2666
|
+
* aligned as the element is
|
|
2667
|
+
* view (`Unmanaged`) — one address: `pointerSize` bits, aligned as a
|
|
2668
|
+
* pointer is
|
|
2669
|
+
* heap (`Managed`) — one GC reference, same shape as the view; the
|
|
2670
|
+
* form itself is refused until Landing 5c, but
|
|
2671
|
+
* the Type can be built so that `sizeof` answers
|
|
2672
|
+
* the truth before the refusal fires
|
|
2673
|
+
*
|
|
2674
|
+
* `pointerSize` is in **bits**, matching `Type.size`.
|
|
2606
2675
|
*/
|
|
2607
|
-
static fixedArray(elementType: Type, length: number): Type;
|
|
2676
|
+
static fixedArray(elementType: Type, length: number, memoryModel: MemoryModelCode, pointerSize: number): Type;
|
|
2608
2677
|
/** Gets the element type of a {@link TypeKind.FixedArray}. */
|
|
2609
2678
|
get fixedArrayElementType(): Type;
|
|
2610
2679
|
/** Interned unmanaged-array types, keyed by element type and pointer width. */
|
|
@@ -3370,6 +3439,31 @@ declare module "types:tensionscript/src/resolver" {
|
|
|
3370
3439
|
* collection wants `Array<T>`, and letting `T[N]` hold references would make
|
|
3371
3440
|
* `@unmanaged` records carry GC edges they cannot describe. Refused by name.
|
|
3372
3441
|
*/
|
|
3442
|
+
/**
|
|
3443
|
+
* Turns on `Feature.MultiValue` the first time a value-form `[T * N]` return
|
|
3444
|
+
* type is resolved.
|
|
3445
|
+
*
|
|
3446
|
+
* **At resolution, not at emission.** The module's feature flags are computed
|
|
3447
|
+
* once, in `Compiler`'s constructor (`module.setFeatures`), and a return is
|
|
3448
|
+
* emitted long after that — so this sets the option *and* re-sets the module's
|
|
3449
|
+
* flags, which `setFeatures` supports (`module.ts`). Measuring that
|
|
3450
|
+
* re-settability is what this hook rests on: with a write-once flags word this
|
|
3451
|
+
* would have needed a deferred second pass.
|
|
3452
|
+
*
|
|
3453
|
+
* Policy is **auto-enable** rather than a required flag: a consumer who writes
|
|
3454
|
+
* `function make(): [T * N]` should not have to know that the emitter lowers it
|
|
3455
|
+
* to multivalue results. The trade is that the module's declared feature set
|
|
3456
|
+
* depends on its source, which is exactly the contract `--exportRuntime`
|
|
3457
|
+
* already sets. A module that never returns one never gets the flag.
|
|
3458
|
+
*
|
|
3459
|
+
* Idempotent: `features` is a bitmask, and re-setting the same flags is a
|
|
3460
|
+
* no-op for binaryen.
|
|
3461
|
+
*/
|
|
3462
|
+
private enableMultiValueForArrayReturn;
|
|
3463
|
+
/** Whether `type` is a fixed array in its **value** form — N inline elements
|
|
3464
|
+
* with no address of their own — as opposed to the `@unmanaged` view (a
|
|
3465
|
+
* pointer) or the `@managed` heap form (Landing 5c). */
|
|
3466
|
+
private isValueFormFixedArray;
|
|
3373
3467
|
private resolveFixedArrayType;
|
|
3374
3468
|
/**
|
|
3375
3469
|
* Resolves an {@link UnmanagedArrayTypeNode} to a
|
|
@@ -4016,7 +4110,7 @@ declare module "types:tensionscript/src/program" {
|
|
|
4016
4110
|
import { Type, Signature } from "types:tensionscript/src/types";
|
|
4017
4111
|
import { Token } from "types:tensionscript/src/tokenizer";
|
|
4018
4112
|
import { Node, Source, DecoratorNode, DecoratorKind, TypeParameterNode, TypeNode, NamedTypeNode, FunctionTypeNode, ArrowKind, Expression, IdentifierExpression, Statement, ClassDeclaration, DeclarationStatement, EnumDeclaration, EnumValueDeclaration, FieldDeclaration, FunctionDeclaration, InterfaceDeclaration, NamespaceDeclaration, TypeDeclaration, VariableDeclaration, VariableLikeDeclarationStatement } from "types:tensionscript/src/ast";
|
|
4019
|
-
import { Module, ExpressionRef, FunctionRef, MemorySegment } from "types:tensionscript/src/module";
|
|
4113
|
+
import { Module, ExpressionRef, FunctionRef, MemorySegment, TypeRef } from "types:tensionscript/src/module";
|
|
4020
4114
|
import { Resolver } from "types:tensionscript/src/resolver";
|
|
4021
4115
|
import { Flow } from "types:tensionscript/src/flow";
|
|
4022
4116
|
import { Parser } from "types:tensionscript/src/parser";
|
|
@@ -4800,6 +4894,29 @@ declare module "types:tensionscript/src/program" {
|
|
|
4800
4894
|
* therefore cannot alias.
|
|
4801
4895
|
*/
|
|
4802
4896
|
fieldLocals: Map<string, Local> | null;
|
|
4897
|
+
/**
|
|
4898
|
+
* The WASM slot type for this local, when it is **not** what {@link type}
|
|
4899
|
+
* says it is.
|
|
4900
|
+
*
|
|
4901
|
+
* `type` answers "what does the source see" — a record, so `p.field` resolves;
|
|
4902
|
+
* an array, so `arr[i]` resolves. The slot is a different question, and for
|
|
4903
|
+
* most locals the two agree. Three cases where they do not:
|
|
4904
|
+
*
|
|
4905
|
+
* - **view local** (`isViewLocal`) — the slot is the pointer; handled below by
|
|
4906
|
+
* substituting `usizeType`, because a pointer *is* a type.
|
|
4907
|
+
* - **multivalue tuple** — the slot is the `TypeRef` binaryen makes for a
|
|
4908
|
+
* multi-result signature. That has **no `Type` at all**: `createType(refs)`
|
|
4909
|
+
* answers a `TypeRef` the type system cannot describe. Hence an override
|
|
4910
|
+
* rather than a substitution — this is the one local whose slot cannot be
|
|
4911
|
+
* named by a `Type`.
|
|
4912
|
+
*
|
|
4913
|
+
* {@link TypeRef.None} for every other local, so the ordinary case costs
|
|
4914
|
+
* nothing — the same reasoning as {@link fieldLocals}. A sentinel rather than
|
|
4915
|
+
* `| null` because `TypeRef` is an integer type and cannot be nullable here
|
|
4916
|
+
* (measured: `AS204: Type 'TypeRef' cannot be nullable` when the self-hosted
|
|
4917
|
+
* compiler parsed this declaration).
|
|
4918
|
+
*/
|
|
4919
|
+
typeRefOverride: TypeRef;
|
|
4803
4920
|
/**
|
|
4804
4921
|
* Whether this local is a **view parameter**: `a: @unmanaged T` where `T` is
|
|
4805
4922
|
* an inline type.
|
|
@@ -4955,6 +5072,23 @@ declare module "types:tensionscript/src/program" {
|
|
|
4955
5072
|
* one structure regardless of where the leaves' storage came from.
|
|
4956
5073
|
*/
|
|
4957
5074
|
bindSroaParameterLeaves(type: Type, path: string, into: Map<string, Local>, localIndex: number, flow: Flow): BindResult;
|
|
5075
|
+
/**
|
|
5076
|
+
* Binds a value-form `[T * N]` parameter's **leaves** to the WASM parameters
|
|
5077
|
+
* that carry them.
|
|
5078
|
+
*
|
|
5079
|
+
* The array sibling of {@link bindSroaParameterLeaves}, and the same tree
|
|
5080
|
+
* shape `fillSroaArrayLocals` builds for a local: the map is keyed `"0"`,
|
|
5081
|
+
* `"1"`, ... and a record element is a placeholder carrying its field leaves.
|
|
5082
|
+
* What differs is where the leaves' storage comes from — incoming parameters
|
|
5083
|
+
* here, fresh locals there.
|
|
5084
|
+
*
|
|
5085
|
+
* Element-major, matching `Signature.leafTypesOf` and the caller's operand
|
|
5086
|
+
* order. A parameter is a **value** for the callee's whole body: nothing is
|
|
5087
|
+
* written back, so a store to `arr[0].x` is invisible to the caller. That is
|
|
5088
|
+
* the copy semantics the representation is for, and it costs nothing extra —
|
|
5089
|
+
* the leaves are separate slots precisely because the value has no address.
|
|
5090
|
+
*/
|
|
5091
|
+
bindSroaArrayParameterLeaves(type: Type, path: string, into: Map<string, Local>, localIndex: number, flow: Flow): BindResult;
|
|
4958
5092
|
/** Constructs a new concrete function. */
|
|
4959
5093
|
constructor(
|
|
4960
5094
|
/** Name incl. type parameters, i.e. `foo<i32>`. */
|
|
@@ -4967,8 +5101,23 @@ declare module "types:tensionscript/src/program" {
|
|
|
4967
5101
|
signature: Signature, // pre-resolved
|
|
4968
5102
|
/** Contextual type arguments inherited from its parent class, if any. */
|
|
4969
5103
|
contextualTypeArguments?: Map<string, Type> | null);
|
|
4970
|
-
/**
|
|
4971
|
-
|
|
5104
|
+
/**
|
|
5105
|
+
* The **WASM slot types** of the additional locals that are not parameters.
|
|
5106
|
+
*
|
|
5107
|
+
* Named for the refs rather than the types because that is what it now
|
|
5108
|
+
* answers: most slots are `local.type.toRef()`, but a multivalue tuple's slot
|
|
5109
|
+
* is a `TypeRef` with no `Type` behind it ({@link Local.typeRefOverride}), and
|
|
5110
|
+
* a view local's slot is the pointer rather than the record it names. Callers
|
|
5111
|
+
* feed this straight to `Module#addFunction`'s `varTypes`, which is a
|
|
5112
|
+
* `TypeRef[]` — so the conversion belongs here, where the slot is decided,
|
|
5113
|
+
* rather than at each of them.
|
|
5114
|
+
*
|
|
5115
|
+
* Renamed from `getNonParameterLocalTypes` when the tuple override landed:
|
|
5116
|
+
* four call sites all wrapped the old answer in `typesToRefs`, and renaming
|
|
5117
|
+
* means a caller that was missed fails to compile instead of silently
|
|
5118
|
+
* declaring a slot of the wrong type.
|
|
5119
|
+
*/
|
|
5120
|
+
getNonParameterLocalTypeRefs(): TypeRef[];
|
|
4972
5121
|
/** Gets the name of the parameter at the specified index. */
|
|
4973
5122
|
getParameterName(index: number): string;
|
|
4974
5123
|
/** Creates a stub for use with this function, i.e. for varargs or override calls. */
|
|
@@ -6474,6 +6623,42 @@ declare module "types:tensionscript/src/compiler" {
|
|
|
6474
6623
|
addDebugLocation(expr: ExpressionRef, range: Range): void;
|
|
6475
6624
|
/** Checks whether a particular function signature is supported. */
|
|
6476
6625
|
checkSignatureSupported(signature: Signature, reportNode: FunctionTypeNode): boolean;
|
|
6626
|
+
/**
|
|
6627
|
+
* The `[T * N]` half of signature support, kept separate so that a refusal
|
|
6628
|
+
* can **stop** the function rather than merely be reported.
|
|
6629
|
+
*
|
|
6630
|
+
* `checkSignatureSupported` reports and compilation carries on — the right
|
|
6631
|
+
* shape for a feature gate, whose codegen path can still produce a module.
|
|
6632
|
+
* Not for this one: a value-form `[T * N]` parameter or return has no slot, so
|
|
6633
|
+
* continuing reaches `Signature#paramRefs` / `#resultRefs`, which call
|
|
6634
|
+
* `toRef`, which asserts for the value form by design. Measured before this
|
|
6635
|
+
* split: `export function f(a: [u32 * 4]): u32` and
|
|
6636
|
+
* `export function f(p: usize): [u32 * 4]` both crashed the compiler inside
|
|
6637
|
+
* `toRef` instead of reporting.
|
|
6638
|
+
*/
|
|
6639
|
+
private checkFixedArrayStorageInSignature;
|
|
6640
|
+
/**
|
|
6641
|
+
* Refuses a `[T * N]` that has no storage in the position it was written in.
|
|
6642
|
+
*
|
|
6643
|
+
* Landing 5a.5 made the memory model part of the Type, which splits the kind
|
|
6644
|
+
* into three: the **view** (`@unmanaged [T * N]`, one address — works
|
|
6645
|
+
* everywhere `@unmanaged T` works), the **heap** form (`@managed [T * N]`,
|
|
6646
|
+
* Landing 5c) and the **value** form (`[T * N]`, `u32[N]`, `@inline [T * N]`
|
|
6647
|
+
* — N inline elements, no address of its own).
|
|
6648
|
+
*
|
|
6649
|
+
* The value form exists and is laid out correctly: it is a record field's
|
|
6650
|
+
* type, `sizeof` counts N × sizeof(T), and Landing 1's fixtures assert all of
|
|
6651
|
+
* that. What it does not have is a **slot**. `toRef` asserts for it by design,
|
|
6652
|
+
* so every position that needs a WASM local, parameter or result must be
|
|
6653
|
+
* refused *before* that assert is reached — otherwise the compiler crashes
|
|
6654
|
+
* where the answer is a diagnostic. Landing 5b gives the form inline storage
|
|
6655
|
+
* (stack slot, copy at the ABI, sret) and these refusals come out.
|
|
6656
|
+
*
|
|
6657
|
+
* This mirrors `Program.checkInlineStructValue`, which refuses the same class
|
|
6658
|
+
* of position for the same reason (a value with no address where one is
|
|
6659
|
+
* needed). `position` names the site so the message says which case was hit.
|
|
6660
|
+
*/
|
|
6661
|
+
private checkFixedArrayStoragePosition;
|
|
6477
6662
|
/** Is `type` an `@inline struct`: a value carried as its fields, never as a
|
|
6478
6663
|
* pointer? */
|
|
6479
6664
|
/**
|
|
@@ -6528,6 +6713,23 @@ declare module "types:tensionscript/src/compiler" {
|
|
|
6528
6713
|
* there is no address to pass. Anything else refuses by name rather than
|
|
6529
6714
|
* compiling a pointer.
|
|
6530
6715
|
*/
|
|
6716
|
+
/**
|
|
6717
|
+
* Expands a value-form `[T * N]` argument into one operand per element leaf.
|
|
6718
|
+
*
|
|
6719
|
+
* Two shapes reach here, and they differ in where the leaves come from:
|
|
6720
|
+
*
|
|
6721
|
+
* - **A value-form local** — push its SROA leaves. `pushSroaLeafOperands`
|
|
6722
|
+
* walks the map depth first through placeholders, which is exactly the
|
|
6723
|
+
* element-major order `paramRefs` declares.
|
|
6724
|
+
* - **An array literal** — compile each element into its own operand. A record
|
|
6725
|
+
* element is several leaves and no literal names them (`{x, y}` goes through
|
|
6726
|
+
* the class path and *allocates*), so it is refused by name, matching
|
|
6727
|
+
* `fillSroaArrayFromLiteral`.
|
|
6728
|
+
*
|
|
6729
|
+
* Anything else — a call returning an array, a conditional — would need the
|
|
6730
|
+
* value materialised somewhere, which is the return path, not this one.
|
|
6731
|
+
*/
|
|
6732
|
+
private expandSroaArrayArgument;
|
|
6531
6733
|
private expandSroaArgument;
|
|
6532
6734
|
/**
|
|
6533
6735
|
* The SROA local an expression names, or `null`.
|
|
@@ -6814,6 +7016,165 @@ declare module "types:tensionscript/src/compiler" {
|
|
|
6814
7016
|
* has already reported why), and the caller has been told.
|
|
6815
7017
|
*/
|
|
6816
7018
|
emitSroaStores(type: Type, fieldLocals: Map<string, Local>, dest: ExpressionRef, baseOffset: number, stmts: ExpressionRef[]): void;
|
|
7019
|
+
/**
|
|
7020
|
+
* Whether `type` is a fixed array in its **value** form — N inline elements,
|
|
7021
|
+
* no address of its own — as opposed to the `@unmanaged` view (a pointer,
|
|
7022
|
+
* Landing 5a.5) or the `@managed` heap form (Landing 5c).
|
|
7023
|
+
*/
|
|
7024
|
+
isValueFormFixedArray(type: Type): boolean;
|
|
7025
|
+
/**
|
|
7026
|
+
* The largest `N` whose value-form array can be indexed with a **runtime**
|
|
7027
|
+
* index.
|
|
7028
|
+
*
|
|
7029
|
+
* A runtime index on SROA leaves has no address to scale, so the element is
|
|
7030
|
+
* selected with a `br_table` over one block per element. Past a handful of
|
|
7031
|
+
* blocks that dispatch costs more than the thing it replaces: the caller who
|
|
7032
|
+
* wants an arbitrary index over many elements wants a pointer, and
|
|
7033
|
+
* `@unmanaged [T * N]` gives them one with no block at all. Eight is the
|
|
7034
|
+
* boundary between the two. Landing 5d's spill strategy is what would lift it.
|
|
7035
|
+
*/
|
|
7036
|
+
private static readonly VALUE_ARRAY_MAX_RUNTIME_INDEX;
|
|
7037
|
+
/** Per-emission counter for the runtime-index block labels, so two accesses in
|
|
7038
|
+
* one function cannot collide (Binaryen requires unique block names). */
|
|
7039
|
+
private sroaSelectId;
|
|
7040
|
+
/**
|
|
7041
|
+
* Fills `into` with one entry per **element** of a value-form `[T * N]`.
|
|
7042
|
+
*
|
|
7043
|
+
* The same shape `fillSroaFieldLocals` gives a record, with the index where
|
|
7044
|
+
* the field name would be: the map is string-keyed and `"0"`, `"1"` are
|
|
7045
|
+
* ordinary keys, so no new container is needed — only a new way to enumerate
|
|
7046
|
+
* the entries.
|
|
7047
|
+
*
|
|
7048
|
+
* - A **scalar** element gets one WASM local, named `<path>$<index>`.
|
|
7049
|
+
* - A **record** element is several leaves, so it gets the placeholder local
|
|
7050
|
+
* (`index -1`) carrying a nested map — exactly what a nested `@inline`
|
|
7051
|
+
* field gets, and for the same reason: `arr[i]` on a record names a whole
|
|
7052
|
+
* sub-value that no single local can hold, while `arr[i].x` descends one
|
|
7053
|
+
* hop to a leaf.
|
|
7054
|
+
*
|
|
7055
|
+
* Returns `false` when an element was refused, having reported why.
|
|
7056
|
+
*/
|
|
7057
|
+
private fillSroaArrayLocals;
|
|
7058
|
+
/**
|
|
7059
|
+
* Compiles a value-form `[T * N]` local as SROA: one WASM local per element
|
|
7060
|
+
* leaf, no local for the array itself, no store for the zero case.
|
|
7061
|
+
*
|
|
7062
|
+
* Returns `true` when the declaration was handled here (the caller must not
|
|
7063
|
+
* fall through to the ordinary local path).
|
|
7064
|
+
*/
|
|
7065
|
+
private compileSroaValueArrayLocal;
|
|
7066
|
+
/**
|
|
7067
|
+
* Stores an array literal's elements into a value-form array's leaves.
|
|
7068
|
+
*
|
|
7069
|
+
* A scalar element is compiled straight into its leaf. A **record** element is
|
|
7070
|
+
* several leaves and a literal cannot name them one at a time, so it is
|
|
7071
|
+
* refused by name here rather than compiled: the object-literal spelling
|
|
7072
|
+
* (`{ x: 1.5, y: 2.5 }`) goes through the class path and *allocates* — measured,
|
|
7073
|
+
* `const p: P = { x: 1.5 }` emitted `P#constructor` plus setters and needed
|
|
7074
|
+
* `env.abort`, i.e. a heap record behind a pointer, which is not a value.
|
|
7075
|
+
* Initialising the elements field by field (`arr[0].x = 10.5`) is the working
|
|
7076
|
+
* route, and it is what the diagnostic says.
|
|
7077
|
+
*/
|
|
7078
|
+
private fillSroaArrayFromLiteral;
|
|
7079
|
+
/**
|
|
7080
|
+
* The local behind `name`, when that local is a value-form `[T * N]` — i.e. a
|
|
7081
|
+
* value stored as one WASM local per element leaf, with no slot of its own.
|
|
7082
|
+
*
|
|
7083
|
+
* Returns `null` for everything else, including the view form (which *is* an
|
|
7084
|
+
* address and goes through the ordinary path).
|
|
7085
|
+
*/
|
|
7086
|
+
private resolveSroaValueArray;
|
|
7087
|
+
/**
|
|
7088
|
+
* The compile-time value of an index expression, or `-1` when it is not a
|
|
7089
|
+
* non-negative integer literal.
|
|
7090
|
+
*
|
|
7091
|
+
* `-1` is the "not constant" answer rather than an error: a runtime index is a
|
|
7092
|
+
* legitimate access, it just takes the `br_table` path.
|
|
7093
|
+
*/
|
|
7094
|
+
private constantIndexValue;
|
|
7095
|
+
/**
|
|
7096
|
+
* Indexes a value-form `[T * N]` local, whose elements are separate WASM
|
|
7097
|
+
* locals.
|
|
7098
|
+
*
|
|
7099
|
+
* A **constant** index needs no dispatch at all: it names one leaf, and the
|
|
7100
|
+
* access is `local.get` / `local.set` on it. A **runtime** index has no address
|
|
7101
|
+
* to scale, so it is selected with a `br_table` over one block per element —
|
|
7102
|
+
* bounded by {@link VALUE_ARRAY_MAX_RUNTIME_INDEX}, past which the caller wants
|
|
7103
|
+
* a pointer view instead.
|
|
7104
|
+
*/
|
|
7105
|
+
private compileSroaValueArrayElementAccess;
|
|
7106
|
+
/**
|
|
7107
|
+
* Selects one element leaf of a value-form array by a runtime index.
|
|
7108
|
+
*
|
|
7109
|
+
* The shape is one `br_table` with a block per element, each block yielding
|
|
7110
|
+
* that element's leaf — the only way to choose between WASM locals at runtime,
|
|
7111
|
+
* since they are not addressable. An index outside `[0, N)` is the caller's
|
|
7112
|
+
* error, exactly as it is for `[T *]`: the extent is compile-time and there is
|
|
7113
|
+
* no length on the value stack to check against.
|
|
7114
|
+
*/
|
|
7115
|
+
private compileSroaValueArrayRuntimeIndex;
|
|
7116
|
+
/**
|
|
7117
|
+
* Reads `arr[i].field` where `arr` is a value-form array **of records** and `i`
|
|
7118
|
+
* is a runtime index. Returns `0` when the shape does not apply.
|
|
7119
|
+
*
|
|
7120
|
+
* A record element is several leaves per candidate, so a single-value
|
|
7121
|
+
* `br_table` cannot select one — but a *field* is one leaf per candidate, so
|
|
7122
|
+
* the selection is per leaf: one block per element, each yielding that
|
|
7123
|
+
* element's `<field>` leaf. Same block nesting as the scalar runtime index
|
|
7124
|
+
* (`compileSroaValueArrayRuntimeIndex`), one hop lower.
|
|
7125
|
+
*
|
|
7126
|
+
* This is the shape the collision solver writes by hand today —
|
|
7127
|
+
* `arr[i].x` with a runtime `i` over a run of records — which is why it is
|
|
7128
|
+
* worth the dispatch rather than only supporting a constant index.
|
|
7129
|
+
*/
|
|
7130
|
+
private compileSroaArrayLeafByRuntimeIndex;
|
|
7131
|
+
/**
|
|
7132
|
+
* Writes `arr[i].field = value` where `arr` is a value-form array of records
|
|
7133
|
+
* and `i` is a runtime index. Returns `0` when the shape does not apply.
|
|
7134
|
+
*
|
|
7135
|
+
* The mirror of {@link compileSroaArrayLeafByRuntimeIndex}: one block per
|
|
7136
|
+
* element, each storing into that element's `<field>` leaf. The value is
|
|
7137
|
+
* materialised into a temp first — one WASM node cannot be the parent of N
|
|
7138
|
+
* stores — which is the same reason the scalar runtime-index write does it.
|
|
7139
|
+
*/
|
|
7140
|
+
private compileSroaArrayLeafStoreByRuntimeIndex;
|
|
7141
|
+
/**
|
|
7142
|
+
* Emits the `br_table` that selects one of `leafIndices` by a runtime index.
|
|
7143
|
+
*
|
|
7144
|
+
* The only way to choose between WASM locals at runtime, since locals are not
|
|
7145
|
+
* addressable: one block per candidate, the body sitting **after** its block's
|
|
7146
|
+
* `end` (where a branch target lands), element 0 as the fall-through.
|
|
7147
|
+
*
|
|
7148
|
+
* One helper rather than four. After Landing 5b.1 four call sites emitted this
|
|
7149
|
+
* same nesting — scalar read, scalar write, record-field read, record-field
|
|
7150
|
+
* write — differing only in which leaf each block touched. Params and returns
|
|
7151
|
+
* would have added more, and a structural bug in one of them would have been
|
|
7152
|
+
* invisible in the other three.
|
|
7153
|
+
*
|
|
7154
|
+
* **A method, not a closure.** The self-hosted compiler refuses an arrow
|
|
7155
|
+
* function that captures a local without a declared type — `AS100: a captured
|
|
7156
|
+
* local without a declared type (closures lowering)` — so the four sites
|
|
7157
|
+
* cannot share a callback.
|
|
7158
|
+
*
|
|
7159
|
+
* `storeValueLocal` is `-1` for a read; for a store it names the temp holding
|
|
7160
|
+
* the value. A store's body cannot reuse the caller's expression tree: a WASM
|
|
7161
|
+
* node has one parent, so N stores cannot share one subtree. `resultType` is
|
|
7162
|
+
* `TypeRef.None` for a store, in which case the dispatch yields nothing.
|
|
7163
|
+
*/
|
|
7164
|
+
private compileLeafIndexSelect;
|
|
7165
|
+
/**
|
|
7166
|
+
* Returns a value-form `[T * N]` value as WASM multivalue results.
|
|
7167
|
+
*
|
|
7168
|
+
* One result per element leaf, element-major — the order `resultRefs` declares
|
|
7169
|
+
* and the caller's unpack indexes into. The leaves are read out of the value's
|
|
7170
|
+
* SROA locals; a fresh array literal goes through the same path, because the
|
|
7171
|
+
* literal binds to leaves before the return is compiled.
|
|
7172
|
+
*
|
|
7173
|
+
* Requires `Feature.MultiValue`, which `Resolver` turns on when it resolves
|
|
7174
|
+
* this return type (`enableMultiValueOnce`), so a module that returns one of
|
|
7175
|
+
* these always has the feature and a module that does not never does.
|
|
7176
|
+
*/
|
|
7177
|
+
private compileMultivalueReturnStatement;
|
|
6817
7178
|
private compileSroaLocal;
|
|
6818
7179
|
/**
|
|
6819
7180
|
* The instance fields of an `@inline struct`, in declaration order, or `null`
|