@yabgu_gm/tensionscript 0.11.0 → 0.11.2
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 +272 -15
- package/dist/asc.js +18 -1
- package/dist/asc.js.map +2 -2
- package/dist/assemblyscript.generated.d.ts +272 -15
- package/dist/assemblyscript.js +40 -40
- package/dist/assemblyscript.js.map +3 -3
- package/dist/importmap.json +2 -2
- package/dist/web.js +3 -3
- package/package.json +1 -1
- package/std/assembly/builtins.ts +15 -0
- package/std/assembly/index.d.ts +2 -0
|
@@ -620,7 +620,9 @@ declare module "types:tensionscript/src/diagnosticMessages.generated" {
|
|
|
620
620
|
_abi_align_0_the_alignment_must_be_a_power_of_two = 6407,
|
|
621
621
|
_abi_align_0_is_less_than_the_field_type_s_natural_alignment_1_asking_for_less_is_a_lie_so_it_is_refused_rather_than_silently_ignored = 6408,
|
|
622
622
|
_abi_align_0_is_too_large_the_maximum_is_1 = 6409,
|
|
623
|
-
Alignment_is_a_property_of_the_field_not_its_type_Place_abi_align_N_on_the_field_declaration = 6410
|
|
623
|
+
Alignment_is_a_property_of_the_field_not_its_type_Place_abi_align_N_on_the_field_declaration = 6410,
|
|
624
|
+
A_view_parameter_unmanaged_0_over_an_inline_type_cannot_appear_in_a_host_visible_signature_an_external_or_exported_parameter_is_supplied_by_the_host_and_a_view_is_an_address_this_compiler_did_not_materialise = 6411,
|
|
625
|
+
Call_to_0_emits_1_operands_but_its_signature_declares_2 = 6412
|
|
624
626
|
}
|
|
625
627
|
/** Translates a diagnostic code to its respective string. */
|
|
626
628
|
export function diagnosticCodeToString(code: DiagnosticCode): string;
|
|
@@ -2706,6 +2708,21 @@ declare module "types:tensionscript/src/types" {
|
|
|
2706
2708
|
* all of them.
|
|
2707
2709
|
*/
|
|
2708
2710
|
static wasmParamCountOf(type: Type): number;
|
|
2711
|
+
/**
|
|
2712
|
+
* Appends the **leaf** types of an `@inline struct`, in declaration order,
|
|
2713
|
+
* depth first.
|
|
2714
|
+
*
|
|
2715
|
+
* A leaf is a field that occupies one WASM local: a scalar or a reference. A
|
|
2716
|
+
* field whose type is itself an `@inline struct` is not a leaf — it is several
|
|
2717
|
+
* locals behind a map — so the walk recurses into it. This is the type-level
|
|
2718
|
+
* twin of the `fieldLocals` tree the compiler builds
|
|
2719
|
+
* (`Compiler#fillSroaFieldLocals`), and the two must agree in **order** as
|
|
2720
|
+
* well as count: the callee binds WASM parameter *k* to the *k*th leaf, and
|
|
2721
|
+
* the caller pushes operands in the same walk.
|
|
2722
|
+
*/
|
|
2723
|
+
static leafTypesOf(type: Type, out: Type[]): void;
|
|
2724
|
+
/** The number of leaf locals an `@inline struct` occupies. */
|
|
2725
|
+
static leafCountOf(type: Type): number;
|
|
2709
2726
|
/**
|
|
2710
2727
|
* How many WASM operands **this signature** spends on source parameter
|
|
2711
2728
|
* `sourceIndex`.
|
|
@@ -2722,6 +2739,18 @@ declare module "types:tensionscript/src/types" {
|
|
|
2722
2739
|
* the same source parameter.
|
|
2723
2740
|
*/
|
|
2724
2741
|
wasmParamSlotCountOf(sourceIndex: number): number;
|
|
2742
|
+
/**
|
|
2743
|
+
* Whether source parameter `sourceIndex` is a **view**: `@unmanaged` at the
|
|
2744
|
+
* declaration over a type that is an `@inline struct`.
|
|
2745
|
+
*
|
|
2746
|
+
* The type still says *value* — every use of `MyStruct` shares one `Type`, and
|
|
2747
|
+
* that is what makes a member lookup work on the parameter — while the model
|
|
2748
|
+
* says this use is an address. One `i32` slot, no field locals, a load at the
|
|
2749
|
+
* field's offset: the same crossing an `@unmanaged struct` parameter already
|
|
2750
|
+
* takes, with the model recorded at the declaration instead of on a pointer
|
|
2751
|
+
* type.
|
|
2752
|
+
*/
|
|
2753
|
+
isViewParam(sourceIndex: number): boolean;
|
|
2725
2754
|
/**
|
|
2726
2755
|
* Whether source parameter `sourceIndex` **crosses by value** — one `i32`
|
|
2727
2756
|
* address instead of one WASM operand per field.
|
|
@@ -2735,8 +2764,12 @@ declare module "types:tensionscript/src/types" {
|
|
|
2735
2764
|
* address, and the override asks for a copy of what is there — the same
|
|
2736
2765
|
* copy, read from memory instead of from SROA locals.
|
|
2737
2766
|
*
|
|
2738
|
-
* The reverse is
|
|
2739
|
-
* declaration is
|
|
2767
|
+
* The reverse is partly a thing now. `@unmanaged` over an `@inline`
|
|
2768
|
+
* declaration is legal where the use supplies an address — a parameter (a
|
|
2769
|
+
* view parameter, `isViewParam`) or `changetype`'s type argument — and a view
|
|
2770
|
+
* parameter crosses as a pointer, so it is asked before this predicate. Every
|
|
2771
|
+
* other cell still refuses (`TS6395`), and `@managed` over `@inline` refuses
|
|
2772
|
+
* at every position: a value has no GC header and no address to lend.
|
|
2740
2773
|
*/
|
|
2741
2774
|
crossesByValueParam(sourceIndex: number): boolean;
|
|
2742
2775
|
/**
|
|
@@ -2759,9 +2792,17 @@ declare module "types:tensionscript/src/types" {
|
|
|
2759
2792
|
get byValPointerParams(): boolean;
|
|
2760
2793
|
/** Whether `type` is an `@inline struct`. */
|
|
2761
2794
|
static isInlineStructRef(type: Type): boolean;
|
|
2762
|
-
/**
|
|
2763
|
-
*
|
|
2764
|
-
*
|
|
2795
|
+
/**
|
|
2796
|
+
* How many **WASM slots** an `@inline struct` spends — its leaf count.
|
|
2797
|
+
*
|
|
2798
|
+
* Leaf count, not direct-field count: a nested inline field is several locals,
|
|
2799
|
+
* so `Outer1 { a: u32; inner: Inner{x,y} }` is 3, not 2. A record with no
|
|
2800
|
+
* members is 0.
|
|
2801
|
+
*
|
|
2802
|
+
* Callers that made sense of "direct fields" are listed in the Phase C audit
|
|
2803
|
+
* (`docs`); the one place that genuinely needs the direct count is layout, and
|
|
2804
|
+
* layout reads `members` itself rather than asking this.
|
|
2805
|
+
*/
|
|
2765
2806
|
static fieldCountOf(type: Type): number;
|
|
2766
2807
|
/**
|
|
2767
2808
|
* Whether a call to this signature passes a hidden destination pointer.
|
|
@@ -3095,6 +3136,60 @@ declare module "types:tensionscript/src/resolver" {
|
|
|
3095
3136
|
currentElementExpression: Expression | null;
|
|
3096
3137
|
/** Whether a new override has been discovered. */
|
|
3097
3138
|
discoveredOverride: boolean;
|
|
3139
|
+
/**
|
|
3140
|
+
* Whether a use-site `@unmanaged` over an `@inline` declaration is being
|
|
3141
|
+
* resolved as the **type argument of `changetype`**.
|
|
3142
|
+
*
|
|
3143
|
+
* That position is the one where the operand can supply the address the value
|
|
3144
|
+
* itself does not have, so the refusal's premise does not hold there (see
|
|
3145
|
+
* `checkMemoryModelOverride`). Every other position — a parameter, a local, a
|
|
3146
|
+
* field, a return type — still refuses with `TS6395`, which is what keeps the
|
|
3147
|
+
* function-parameter form (`Phase 2`) out of this change.
|
|
3148
|
+
*
|
|
3149
|
+
* The compiler sets this around the one `resolveTypeArguments` call it makes
|
|
3150
|
+
* for a `changetype` builtin (`Compiler#compileCallExpressionBuiltin`), and
|
|
3151
|
+
* resets it immediately: the flag is a scope, not a mode.
|
|
3152
|
+
*/
|
|
3153
|
+
allowInlineView: boolean;
|
|
3154
|
+
/**
|
|
3155
|
+
* Whether a use-site `@unmanaged` over an `@inline` declaration is being
|
|
3156
|
+
* resolved in a **parameter position** — the cell where the caller supplies
|
|
3157
|
+
* the address, so `f(a: @unmanaged T)` with an inline `T` is a view parameter.
|
|
3158
|
+
*
|
|
3159
|
+
* Distinct from {@link allowInlineView} (Phase 1, `changetype`'s type
|
|
3160
|
+
* argument, where the operand supplies the address at the point of use).
|
|
3161
|
+
*
|
|
3162
|
+
* **Saved and restored, never blindly cleared.** Resolving one parameter's
|
|
3163
|
+
* type can resolve another function (a default value's call, a nested
|
|
3164
|
+
* signature), and a nested window that reset the flag to `false` on the way
|
|
3165
|
+
* out closed the outer window — measured: the owner's pattern reported TS6395
|
|
3166
|
+
* with both flags reading `false` while inside `resolveFunction`'s own loop.
|
|
3167
|
+
*/
|
|
3168
|
+
allowInlineViewParam: boolean;
|
|
3169
|
+
/**
|
|
3170
|
+
* Call expressions that are **views of caller bytes**: an inline-typed
|
|
3171
|
+
* `changetype<@unmanaged T>(ptr)`.
|
|
3172
|
+
*
|
|
3173
|
+
* Marked here, at resolution, because the compiler asks this question while
|
|
3174
|
+
* compiling the *field access* — which happens before the `changetype` it
|
|
3175
|
+
* wraps is ever compiled. Recording it at codegen time (the first attempt)
|
|
3176
|
+
* produced a field read that never saw the mark and compiled to
|
|
3177
|
+
* `unreachable`.
|
|
3178
|
+
*
|
|
3179
|
+
* Keyed on the AST node rather than on the type, because the type is the
|
|
3180
|
+
* declaration's (`T` is still an `@inline struct`) and the model is the
|
|
3181
|
+
* *use's*: there is one `Type` per class, shared by every use.
|
|
3182
|
+
*/
|
|
3183
|
+
private viewCalls;
|
|
3184
|
+
/**
|
|
3185
|
+
* Records `node` as a view call. The resolver marks the ones it resolves;
|
|
3186
|
+
* `Compiler#compileCallExpressionBuiltin` marks the ones it resolves itself,
|
|
3187
|
+
* because a builtin's type arguments are resolved on the *codegen* path and
|
|
3188
|
+
* never pass through `maybeInferCall`.
|
|
3189
|
+
*/
|
|
3190
|
+
markViewCall(node: Expression): void;
|
|
3191
|
+
/** Whether `node` is an inline-typed `changetype<@unmanaged T>(...)`. */
|
|
3192
|
+
isViewCall(node: Expression): boolean;
|
|
3098
3193
|
/** Constructs the resolver for the specified program. */
|
|
3099
3194
|
constructor(
|
|
3100
3195
|
/** The program to construct a resolver for. */
|
|
@@ -3122,10 +3217,14 @@ declare module "types:tensionscript/src/resolver" {
|
|
|
3122
3217
|
* - **`@managed` over an `@unmanaged` declaration** — the collector traces a
|
|
3123
3218
|
* reference through a header the record does not have. No emitter can
|
|
3124
3219
|
* invent the header, so a use cannot confer provenance. (`TS6394`.)
|
|
3125
|
-
* - **`@
|
|
3126
|
-
*
|
|
3127
|
-
*
|
|
3128
|
-
* (
|
|
3220
|
+
* - **`@managed` over an `@inline` declaration** — a value has neither a
|
|
3221
|
+
* header nor an address, at any position. (`TS6395`.)
|
|
3222
|
+
* - **`@unmanaged` over an `@inline` declaration**, *except* where the use
|
|
3223
|
+
* supplies an address: `changetype`'s type argument (the operand supplies
|
|
3224
|
+
* it) and a parameter (the caller supplies it). Those two windows are
|
|
3225
|
+
* `allowInlineView` and `allowInlineViewParam`, and they are the whole
|
|
3226
|
+
* difference between a view and a claim. Every other position — a return
|
|
3227
|
+
* type, a local, a field — still has nothing to lend. (`TS6395`.)
|
|
3129
3228
|
*
|
|
3130
3229
|
* Everything else is left to the emitters: `@unmanaged` over `@managed` is
|
|
3131
3230
|
* the identity cell (10.0a), `@inline` over a pointer declaration is the
|
|
@@ -3763,6 +3862,14 @@ declare module "types:tensionscript/src/program" {
|
|
|
3763
3862
|
function fromUnaryPostfixToken(token: Token): OperatorKind;
|
|
3764
3863
|
}
|
|
3765
3864
|
/** Represents an AssemblyScript program. */
|
|
3865
|
+
/** How many WASM slots a parameter binding consumed — see
|
|
3866
|
+
* `Program#bindSroaParameterLeaves`. A one-field wrapper because this compiler
|
|
3867
|
+
* reports the count and the caller advances past it; a bare `i32` return would
|
|
3868
|
+
* be the same information with no name at the call site. */
|
|
3869
|
+
export class BindResult {
|
|
3870
|
+
leafCount: number;
|
|
3871
|
+
constructor(leafCount: number);
|
|
3872
|
+
}
|
|
3766
3873
|
export class Program extends DiagnosticEmitter {
|
|
3767
3874
|
/** Compiler options. */
|
|
3768
3875
|
options: Options;
|
|
@@ -4479,6 +4586,17 @@ declare module "types:tensionscript/src/program" {
|
|
|
4479
4586
|
* therefore cannot alias.
|
|
4480
4587
|
*/
|
|
4481
4588
|
fieldLocals: Map<string, Local> | null;
|
|
4589
|
+
/**
|
|
4590
|
+
* Whether this local is a **view parameter**: `a: @unmanaged T` where `T` is
|
|
4591
|
+
* an inline type.
|
|
4592
|
+
*
|
|
4593
|
+
* Its `type` is still the inline record, because that is what makes `a.field`
|
|
4594
|
+
* resolve — every use of `T` shares one `Type`. Its *storage* is the one `i32`
|
|
4595
|
+
* WASM parameter holding the caller's address, which is why a field read goes
|
|
4596
|
+
* through `load` at the field's offset rather than through `fieldLocals`
|
|
4597
|
+
* (there are none: a view has no per-field locals to copy into).
|
|
4598
|
+
*/
|
|
4599
|
+
isViewParam: boolean;
|
|
4482
4600
|
/** Constructs a new local variable. */
|
|
4483
4601
|
constructor(
|
|
4484
4602
|
/** Simple name. */
|
|
@@ -4590,6 +4708,20 @@ declare module "types:tensionscript/src/program" {
|
|
|
4590
4708
|
nextInlineId: number;
|
|
4591
4709
|
/** Counting id of anonymous inner functions. */
|
|
4592
4710
|
nextAnonymousId: number;
|
|
4711
|
+
/**
|
|
4712
|
+
* Binds an `@inline struct` parameter's **leaves** to the WASM parameters that
|
|
4713
|
+
* carry them, building the `fieldLocals` tree a read path walks.
|
|
4714
|
+
*
|
|
4715
|
+
* `localIndex` is the index of the parameter's first WASM slot; the walk
|
|
4716
|
+
* consumes one slot per leaf in the same depth-first order
|
|
4717
|
+
* `Signature.leafTypesOf` declares and the caller pushes operands in. Returns
|
|
4718
|
+
* how many slots were consumed, so the caller advances past them.
|
|
4719
|
+
*
|
|
4720
|
+
* A nested field gets a placeholder `Local` (index `-1`) carrying its own map,
|
|
4721
|
+
* exactly as `fillSroaFieldLocals` builds one for a local — the tree shape is
|
|
4722
|
+
* one structure regardless of where the leaves' storage came from.
|
|
4723
|
+
*/
|
|
4724
|
+
bindSroaParameterLeaves(type: Type, path: string, into: Map<string, Local>, localIndex: number, flow: Flow): BindResult;
|
|
4593
4725
|
/** Constructs a new concrete function. */
|
|
4594
4726
|
constructor(
|
|
4595
4727
|
/** Name incl. type parameters, i.e. `foo<i32>`. */
|
|
@@ -5284,7 +5416,7 @@ declare module "types:tensionscript/src/compiler" {
|
|
|
5284
5416
|
import { Range, DiagnosticEmitter } from "types:tensionscript/src/diagnostics";
|
|
5285
5417
|
import { Module, MemorySegment, ExpressionRef, TypeRef, GlobalRef } from "types:tensionscript/src/module";
|
|
5286
5418
|
import { Feature, Target, Runtime } from "types:tensionscript/src/common";
|
|
5287
|
-
import { Program, Class, Element, DeclaredElement, Enum, Function, Global, Property, VariableLikeElement, File } from "types:tensionscript/src/program";
|
|
5419
|
+
import { Program, Class, Element, DeclaredElement, Enum, Function, Global, Local, Property, VariableLikeElement, File } from "types:tensionscript/src/program";
|
|
5288
5420
|
import { Flow, ConditionKind } from "types:tensionscript/src/flow";
|
|
5289
5421
|
import { Resolver } from "types:tensionscript/src/resolver";
|
|
5290
5422
|
import { Node, FunctionTypeNode, Statement, Expression } from "types:tensionscript/src/ast";
|
|
@@ -5770,6 +5902,18 @@ declare module "types:tensionscript/src/compiler" {
|
|
|
5770
5902
|
private needToStack;
|
|
5771
5903
|
/** Marks managed call operands for the shadow stack. */
|
|
5772
5904
|
private operandsTostack;
|
|
5905
|
+
/**
|
|
5906
|
+
* Checks that the operands about to be passed match the WASM arity the callee
|
|
5907
|
+
* declares, and reports a clean diagnostic when they do not.
|
|
5908
|
+
*
|
|
5909
|
+
* The invariant is maintained by the default-argument filling in
|
|
5910
|
+
* `makeCallDirect`; this guard exists because when that filling misses — as it
|
|
5911
|
+
* did for an sret callee with an omitted optional argument — the mismatch
|
|
5912
|
+
* reached the WASM validator as `call* param number must match`, which names a
|
|
5913
|
+
* binaryen rule and never mentions the call that broke it. A wrong arity is a
|
|
5914
|
+
* compiler bug, so it should say so at the call site.
|
|
5915
|
+
*/
|
|
5916
|
+
private checkCallArity;
|
|
5773
5917
|
/** Creates a direct call to the specified function. */
|
|
5774
5918
|
makeCallDirect(instance: Function, operands: ExpressionRef[] | null, reportNode: Node, immediatelyDropped?: boolean): ExpressionRef;
|
|
5775
5919
|
/** Compiles an indirect call to a first-class function. */
|
|
@@ -5947,11 +6091,27 @@ declare module "types:tensionscript/src/compiler" {
|
|
|
5947
6091
|
/**
|
|
5948
6092
|
* The SROA local an expression names, or `null`.
|
|
5949
6093
|
*
|
|
5950
|
-
*
|
|
5951
|
-
*
|
|
5952
|
-
*
|
|
5953
|
-
*
|
|
6094
|
+
* The receiver is either an SROA local (base identifier) or a chain of field
|
|
6095
|
+
* accesses into one (`o.inner` in `o.inner.x`). The chain is walked from the
|
|
6096
|
+
* base outward, one hop per `fieldLocals` lookup: a nested inline field is
|
|
6097
|
+
* entered through the placeholder `Local` its creation installed
|
|
6098
|
+
* (`fillSroaFieldLocals`), so the walk and the tree are one structure rather
|
|
6099
|
+
* than two that could disagree.
|
|
6100
|
+
*
|
|
6101
|
+
* Returns the `Local` the final hop resolved to, or `null` when any step does
|
|
6102
|
+
* not hold — a non-local base, a field with no entry, or a leaf reached before
|
|
6103
|
+
* the chain ends. `null` is not an error here: the caller falls through to the
|
|
6104
|
+
* ordinary address paths, which refuse a value with no address.
|
|
5954
6105
|
*/
|
|
6106
|
+
/**
|
|
6107
|
+
* Pushes one operand per **leaf** of a `fieldLocals` tree, depth first.
|
|
6108
|
+
*
|
|
6109
|
+
* Shared by the call site (`expandSroaArgument`) so the operand order is the
|
|
6110
|
+
* one `Signature.leafTypesOf` declares and the binder indexes into — three
|
|
6111
|
+
* walks, one order. A nested field's entry is a placeholder (index `-1`)
|
|
6112
|
+
* carrying its own map, so the walk descends through it.
|
|
6113
|
+
*/
|
|
6114
|
+
private pushSroaLeafOperands;
|
|
5955
6115
|
private resolveSroaReceiver;
|
|
5956
6116
|
/** Size of the static call-temp region, in bytes. 4 KB is 256 slots at the
|
|
5957
6117
|
* 16-byte fixture record size. Overflow aborts (see `makeSretCallBlock`);
|
|
@@ -6041,6 +6201,15 @@ declare module "types:tensionscript/src/compiler" {
|
|
|
6041
6201
|
/** `base + mark + extra`, freshly built. Callers must not share the node:
|
|
6042
6202
|
* Binaryen's passes assume a single parent per expression. */
|
|
6043
6203
|
private makeSretAddressPlus;
|
|
6204
|
+
/**
|
|
6205
|
+
* Stores a by-value argument's leaves into the static call-temp region.
|
|
6206
|
+
*
|
|
6207
|
+
* The same tree walk as `copyInto` (`emitSroaStores`) and `copySroaValue`:
|
|
6208
|
+
* leaves become stores at `tempAddress + field offset`, a nested field is
|
|
6209
|
+
* descended into. Keeping one recursion is what makes a nested value cross a
|
|
6210
|
+
* host boundary at the layout the C side expects.
|
|
6211
|
+
*/
|
|
6212
|
+
emitTempArgumentLeaves(type: Type, fieldLocals: Map<string, Local>, base: number, markLocal: Local, baseOffset: number, stmts: ExpressionRef[]): void;
|
|
6044
6213
|
/**
|
|
6045
6214
|
* Materialises one `@inline struct` argument of an `@external` call on the
|
|
6046
6215
|
* static call-temp stack and returns the address to pass.
|
|
@@ -6111,6 +6280,93 @@ declare module "types:tensionscript/src/compiler" {
|
|
|
6111
6280
|
* Returns true when the declaration was handled here (the caller must not fall
|
|
6112
6281
|
* through to the ordinary local path).
|
|
6113
6282
|
*/
|
|
6283
|
+
/**
|
|
6284
|
+
* Fills `into` with one entry per field of an `@inline struct` value.
|
|
6285
|
+
*
|
|
6286
|
+
* A **leaf** field (scalar, or a reference) gets one WASM local, named
|
|
6287
|
+
* `<path>$<field>` — a synthetic name keeps it out of user scope, so nothing
|
|
6288
|
+
* can look one up by accident.
|
|
6289
|
+
*
|
|
6290
|
+
* A field whose type is itself an `@inline struct` is **not a leaf**: it is
|
|
6291
|
+
* recursed into, and its entry is a placeholder `Local` (index `-1`) carrying
|
|
6292
|
+
* its own map. That makes `fieldLocals` a **tree** whose shape is the value's
|
|
6293
|
+
* nesting, which is what lets a read path walk `o.inner.x` a hop at a time
|
|
6294
|
+
* without a second representation. The placeholder is never `local.get`-ed:
|
|
6295
|
+
* the bare-read guard refuses a value read and the receiver walk descends to
|
|
6296
|
+
* a leaf before emitting anything.
|
|
6297
|
+
*
|
|
6298
|
+
* Returns `false` when a field was refused, having reported why. The refusal
|
|
6299
|
+
* is per **leaf**, so a nested value inherits exactly the rules the flat one
|
|
6300
|
+
* has — a `T[N]` field or a GC-reference field is refused at any depth.
|
|
6301
|
+
*/
|
|
6302
|
+
private fillSroaFieldLocals;
|
|
6303
|
+
/**
|
|
6304
|
+
* Copies one SROA value's leaves into another's, following the tree.
|
|
6305
|
+
*
|
|
6306
|
+
* `from` and `to` are the two `fieldLocals` maps — the same shape
|
|
6307
|
+
* `fillSroaFieldLocals` builds, so a nested field is a placeholder on both
|
|
6308
|
+
* sides and the recursion descends through it rather than trying to move a
|
|
6309
|
+
* value that has no single representation.
|
|
6310
|
+
*
|
|
6311
|
+
* This is what makes `let q = p` and `q = p` **copies** rather than aliases:
|
|
6312
|
+
* one `local.set` per leaf, so a later write to `q` cannot be seen through
|
|
6313
|
+
* `p`. Both sides come from this compiler's own maps, so there is no aliasing
|
|
6314
|
+
* question to answer — the leaves are distinct locals by construction.
|
|
6315
|
+
*/
|
|
6316
|
+
private copySroaValue;
|
|
6317
|
+
/**
|
|
6318
|
+
* Stores a `fieldLocals` tree's leaves into the hidden destination slot at
|
|
6319
|
+
* `destIndex`, one store per leaf.
|
|
6320
|
+
*
|
|
6321
|
+
* The third destination shape for the same recursion: `emitSroaStores` writes
|
|
6322
|
+
* to a compiled `usize`, `emitTempArgumentLeaves` to a call-temp address, and
|
|
6323
|
+
* this one to a **parameter** — the sret slot a `return p` fills. The address
|
|
6324
|
+
* is a fresh `local.get` per store, because Binaryen's passes assume one
|
|
6325
|
+
* parent per node.
|
|
6326
|
+
*/
|
|
6327
|
+
emitSroaStoresToLocal(type: Type, fieldLocals: Map<string, Local>, destIndex: number, baseOffset: number, stmts: ExpressionRef[]): void;
|
|
6328
|
+
/**
|
|
6329
|
+
* Zeroes every **leaf** of an `@inline struct` in the destination slot.
|
|
6330
|
+
*
|
|
6331
|
+
* `return new P()` has no local to copy from — the value is all zeroes — but
|
|
6332
|
+
* the slot is stack space that a previous sret call may have filled, so the
|
|
6333
|
+
* bytes still have to be written. Walking the type rather than the direct
|
|
6334
|
+
* fields is what zeroes a nested field's leaves: measured before this,
|
|
6335
|
+
* `return new Outer1()` with `Inner{x,y}` stored only offset 0 and left
|
|
6336
|
+
* offsets 4 and 8 holding whatever was there.
|
|
6337
|
+
*/
|
|
6338
|
+
emitSroaZerosToLocal(type: Type, destIndex: number, baseOffset: number, stmts: ExpressionRef[]): void;
|
|
6339
|
+
/**
|
|
6340
|
+
* Loads an `@inline struct`'s leaves out of the sret slot into a target's
|
|
6341
|
+
* field locals, one load per leaf.
|
|
6342
|
+
*
|
|
6343
|
+
* The mirror of {@link emitSroaStoresToLocal}: `let q = make()` reads the slot
|
|
6344
|
+
* back into the leaf locals a read path walks. A fresh slot address per load,
|
|
6345
|
+
* for the same one-parent-per-node reason.
|
|
6346
|
+
*/
|
|
6347
|
+
emitSretLoadsInto(type: Type, fieldLocals: Map<string, Local>, base: number, markLocal: Local, baseOffset: number, stmts: ExpressionRef[]): void;
|
|
6348
|
+
/**
|
|
6349
|
+
* The `fieldLocals` tree behind an SROA-tracked expression, or `null`.
|
|
6350
|
+
*
|
|
6351
|
+
* The public face of {@link resolveSroaReceiver} for code outside this class —
|
|
6352
|
+
* today only the `copyInto` builtin, which needs the *tree* (to store its
|
|
6353
|
+
* leaves) rather than a single receiver.
|
|
6354
|
+
*/
|
|
6355
|
+
sroaTreeOf(expression: Expression): Map<string, Local> | null;
|
|
6356
|
+
/**
|
|
6357
|
+
* Stores an inline value's leaves at `dest + offset`.
|
|
6358
|
+
*
|
|
6359
|
+
* The third leaf consumer, beside `copySroaValue` (local-to-local) and the
|
|
6360
|
+
* read path (local-to-stack): same tree, same recursion, an expression
|
|
6361
|
+
* reference instead of a destination map. The offsets come from the **type**
|
|
6362
|
+
* (`property.memoryOffset`, the layout the C side sees), so what lands in
|
|
6363
|
+
* memory is the wire layout, not a packing of the locals.
|
|
6364
|
+
*
|
|
6365
|
+
* Leaves whose local is missing are skipped rather than stored as `-1`: a
|
|
6366
|
+
* field refused at declaration was never part of the value (`isSroaFieldType`
|
|
6367
|
+
* has already reported why), and the caller has been told.
|
|
6368
|
+
*/
|
|
6369
|
+
emitSroaStores(type: Type, fieldLocals: Map<string, Local>, dest: ExpressionRef, baseOffset: number, stmts: ExpressionRef[]): void;
|
|
6114
6370
|
private compileSroaLocal;
|
|
6115
6371
|
/**
|
|
6116
6372
|
* The instance fields of an `@inline struct`, in declaration order, or `null`
|
|
@@ -6296,6 +6552,7 @@ declare module "types:tensionscript/src/builtins" {
|
|
|
6296
6552
|
const select = "~lib/builtins/select";
|
|
6297
6553
|
const unreachable = "~lib/builtins/unreachable";
|
|
6298
6554
|
const changetype = "~lib/builtins/changetype";
|
|
6555
|
+
const copyInto = "~lib/builtins/copyInto";
|
|
6299
6556
|
const assert = "~lib/builtins/assert";
|
|
6300
6557
|
const call_indirect = "~lib/builtins/call_indirect";
|
|
6301
6558
|
const unchecked = "~lib/builtins/unchecked";
|