@loopdive/js2 0.57.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/CHANGELOG.md +1425 -0
- package/LICENSE +189 -0
- package/README.md +451 -0
- package/dist/checker/index.d.ts +117 -0
- package/dist/checker/language-service.d.ts +39 -0
- package/dist/checker/node-capability-map.d.ts +63 -0
- package/dist/checker/type-mapper.d.ts +84 -0
- package/dist/cjs-rewrite.d.ts +19 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +363 -0
- package/dist/codegen/accessor-driver.d.ts +97 -0
- package/dist/codegen/any-helpers.d.ts +72 -0
- package/dist/codegen/array-element-typing.d.ts +46 -0
- package/dist/codegen/array-holes.d.ts +69 -0
- package/dist/codegen/array-methods.d.ts +68 -0
- package/dist/codegen/array-object-proto.d.ts +64 -0
- package/dist/codegen/array-reduce-fusion.d.ts +31 -0
- package/dist/codegen/array-to-primitive.d.ts +28 -0
- package/dist/codegen/async-cps.d.ts +239 -0
- package/dist/codegen/async-scheduler.d.ts +349 -0
- package/dist/codegen/binary-ops.d.ts +78 -0
- package/dist/codegen/binding-info.d.ts +31 -0
- package/dist/codegen/builtin-scaffold.d.ts +98 -0
- package/dist/codegen/builtin-static-globals.d.ts +8 -0
- package/dist/codegen/builtin-tags.d.ts +189 -0
- package/dist/codegen/case-convert-native.d.ts +12 -0
- package/dist/codegen/case-tables.d.ts +4 -0
- package/dist/codegen/class-bodies.d.ts +41 -0
- package/dist/codegen/class-member-keys.d.ts +33 -0
- package/dist/codegen/class-to-primitive.d.ts +39 -0
- package/dist/codegen/closed-method-dispatch.d.ts +42 -0
- package/dist/codegen/closures.d.ts +285 -0
- package/dist/codegen/coercion-engine.d.ts +154 -0
- package/dist/codegen/coercion-plan.d.ts +29 -0
- package/dist/codegen/context/bodies.d.ts +4 -0
- package/dist/codegen/context/create-context.d.ts +4 -0
- package/dist/codegen/context/errors.d.ts +39 -0
- package/dist/codegen/context/locals.d.ts +69 -0
- package/dist/codegen/context/source-pos.d.ts +5 -0
- package/dist/codegen/context/speculative.d.ts +95 -0
- package/dist/codegen/context/types.d.ts +1936 -0
- package/dist/codegen/custom-iterable.d.ts +34 -0
- package/dist/codegen/dataview-native.d.ts +51 -0
- package/dist/codegen/date-parse-native.d.ts +13 -0
- package/dist/codegen/dead-elimination.d.ts +26 -0
- package/dist/codegen/declarations.d.ts +147 -0
- package/dist/codegen/deno-api.d.ts +11 -0
- package/dist/codegen/destructuring-params.d.ts +102 -0
- package/dist/codegen/dyn-read.d.ts +26 -0
- package/dist/codegen/eval-tiering.d.ts +19 -0
- package/dist/codegen/expressions/assignment.d.ts +61 -0
- package/dist/codegen/expressions/builtins.d.ts +26 -0
- package/dist/codegen/expressions/calls-closures.d.ts +54 -0
- package/dist/codegen/expressions/calls-guards.d.ts +49 -0
- package/dist/codegen/expressions/calls-optional.d.ts +4 -0
- package/dist/codegen/expressions/calls.d.ts +83 -0
- package/dist/codegen/expressions/eval-inline.d.ts +24 -0
- package/dist/codegen/expressions/extern.d.ts +67 -0
- package/dist/codegen/expressions/fnctor-prototype.d.ts +52 -0
- package/dist/codegen/expressions/helpers.d.ts +212 -0
- package/dist/codegen/expressions/identifiers.d.ts +57 -0
- package/dist/codegen/expressions/late-imports.d.ts +81 -0
- package/dist/codegen/expressions/logical-ops.d.ts +18 -0
- package/dist/codegen/expressions/misc.d.ts +27 -0
- package/dist/codegen/expressions/new-super.d.ts +25 -0
- package/dist/codegen/expressions/promise-subclass.d.ts +38 -0
- package/dist/codegen/expressions/proto-override.d.ts +63 -0
- package/dist/codegen/expressions/unary-updates.d.ts +21 -0
- package/dist/codegen/expressions/unary.d.ts +6 -0
- package/dist/codegen/expressions.d.ts +31 -0
- package/dist/codegen/fallback-telemetry.d.ts +53 -0
- package/dist/codegen/fixups.d.ts +80 -0
- package/dist/codegen/fmod.d.ts +10 -0
- package/dist/codegen/fnctor-escape-gate.d.ts +92 -0
- package/dist/codegen/function-body.d.ts +52 -0
- package/dist/codegen/generators-native.d.ts +92 -0
- package/dist/codegen/helpers/body-references-own-this.d.ts +22 -0
- package/dist/codegen/helpers/body-uses-arguments.d.ts +12 -0
- package/dist/codegen/helpers/is-strict-function.d.ts +52 -0
- package/dist/codegen/host-import-allowlist.d.ts +140 -0
- package/dist/codegen/index.d.ts +500 -0
- package/dist/codegen/ir-tail-call.d.ts +8 -0
- package/dist/codegen/iterator-native.d.ts +44 -0
- package/dist/codegen/json-codec-native.d.ts +78 -0
- package/dist/codegen/json-runtime.d.ts +35 -0
- package/dist/codegen/json-standalone.d.ts +25 -0
- package/dist/codegen/linear-uint8-analysis.d.ts +46 -0
- package/dist/codegen/linear-uint8-arena.d.ts +7 -0
- package/dist/codegen/linear-uint8-codegen.d.ts +103 -0
- package/dist/codegen/linear-uint8-signatures.d.ts +26 -0
- package/dist/codegen/literals.d.ts +115 -0
- package/dist/codegen/map-runtime.d.ts +142 -0
- package/dist/codegen/math-helpers.d.ts +7 -0
- package/dist/codegen/member-get-dispatch.d.ts +42 -0
- package/dist/codegen/member-set-dispatch.d.ts +28 -0
- package/dist/codegen/native-proto.d.ts +98 -0
- package/dist/codegen/native-regex.d.ts +158 -0
- package/dist/codegen/native-strings.d.ts +146 -0
- package/dist/codegen/new-target.d.ts +30 -0
- package/dist/codegen/node-fs-api.d.ts +47 -0
- package/dist/codegen/number-format-native.d.ts +9 -0
- package/dist/codegen/number-ryu.d.ts +27 -0
- package/dist/codegen/object-ops.d.ts +94 -0
- package/dist/codegen/object-runtime.d.ts +171 -0
- package/dist/codegen/parse-number-native.d.ts +10 -0
- package/dist/codegen/peephole.d.ts +6 -0
- package/dist/codegen/property-access.d.ts +294 -0
- package/dist/codegen/raw-wasi-api.d.ts +13 -0
- package/dist/codegen/regex/bytecode.d.ts +140 -0
- package/dist/codegen/regex/casefold.d.ts +41 -0
- package/dist/codegen/regex/compile.d.ts +51 -0
- package/dist/codegen/regex/parse.d.ts +76 -0
- package/dist/codegen/regex/unicode.d.ts +42 -0
- package/dist/codegen/regex/vm.d.ts +24 -0
- package/dist/codegen/regexp-standalone.d.ts +350 -0
- package/dist/codegen/registry/error-types.d.ts +38 -0
- package/dist/codegen/registry/imports.d.ts +46 -0
- package/dist/codegen/registry/types.d.ts +59 -0
- package/dist/codegen/set-algebra.d.ts +17 -0
- package/dist/codegen/set-runtime.d.ts +74 -0
- package/dist/codegen/shared.d.ts +111 -0
- package/dist/codegen/stack-balance.d.ts +43 -0
- package/dist/codegen/statements/control-flow.d.ts +25 -0
- package/dist/codegen/statements/destructuring.d.ts +177 -0
- package/dist/codegen/statements/exceptions.d.ts +11 -0
- package/dist/codegen/statements/functions.d.ts +1 -0
- package/dist/codegen/statements/index.d.ts +1 -0
- package/dist/codegen/statements/loops.d.ts +7 -0
- package/dist/codegen/statements/nested-declarations.d.ts +78 -0
- package/dist/codegen/statements/shared.d.ts +38 -0
- package/dist/codegen/statements/tdz.d.ts +43 -0
- package/dist/codegen/statements/variables.d.ts +3 -0
- package/dist/codegen/statements.d.ts +9 -0
- package/dist/codegen/string-builder.d.ts +131 -0
- package/dist/codegen/string-ops.d.ts +87 -0
- package/dist/codegen/struct-accessor-closure.d.ts +36 -0
- package/dist/codegen/symbol-native.d.ts +55 -0
- package/dist/codegen/temporal-native.d.ts +8 -0
- package/dist/codegen/timsort.d.ts +2 -0
- package/dist/codegen/type-coercion.d.ts +123 -0
- package/dist/codegen/typeof-delete.d.ts +38 -0
- package/dist/codegen/uri-encoding-native.d.ts +33 -0
- package/dist/codegen/value-tags.d.ts +74 -0
- package/dist/codegen/walk-instructions.d.ts +20 -0
- package/dist/codegen/weak-collections-runtime.d.ts +16 -0
- package/dist/codegen/with-scope.d.ts +106 -0
- package/dist/codegen-linear/c-abi.d.ts +74 -0
- package/dist/codegen-linear/context.d.ts +86 -0
- package/dist/codegen-linear/index.d.ts +28 -0
- package/dist/codegen-linear/layout.d.ts +39 -0
- package/dist/codegen-linear/runtime.d.ts +161 -0
- package/dist/codegen-linear/simd.d.ts +7 -0
- package/dist/compiler/define-substitution.d.ts +27 -0
- package/dist/compiler/early-errors/assignment.d.ts +26 -0
- package/dist/compiler/early-errors/context.d.ts +17 -0
- package/dist/compiler/early-errors/duplicates.d.ts +20 -0
- package/dist/compiler/early-errors/index.d.ts +11 -0
- package/dist/compiler/early-errors/labels.d.ts +13 -0
- package/dist/compiler/early-errors/module-rules.d.ts +36 -0
- package/dist/compiler/early-errors/node-checks.d.ts +7 -0
- package/dist/compiler/early-errors/predicates.d.ts +140 -0
- package/dist/compiler/early-errors/tdz.d.ts +17 -0
- package/dist/compiler/import-manifest.d.ts +18 -0
- package/dist/compiler/output.d.ts +46 -0
- package/dist/compiler/validation.d.ts +45 -0
- package/dist/compiler.d.ts +48 -0
- package/dist/define-substitution-BcUeKC2A.js +109 -0
- package/dist/emit/binary.d.ts +50 -0
- package/dist/emit/c-header.d.ts +23 -0
- package/dist/emit/canonical-recgroup.d.ts +86 -0
- package/dist/emit/encoder.d.ts +28 -0
- package/dist/emit/object.d.ts +14 -0
- package/dist/emit/opcodes.d.ts +464 -0
- package/dist/emit/sourcemap.d.ts +33 -0
- package/dist/emit/wat.d.ts +6 -0
- package/dist/env.d.ts +46 -0
- package/dist/import-resolver.d.ts +68 -0
- package/dist/index.d.ts +486 -0
- package/dist/index.js +755 -0
- package/dist/ir/alloc-registry.d.ts +75 -0
- package/dist/ir/analysis/encoding.d.ts +38 -0
- package/dist/ir/analysis/escape.d.ts +32 -0
- package/dist/ir/analysis/lattice.d.ts +72 -0
- package/dist/ir/analysis/ownership.d.ts +31 -0
- package/dist/ir/analysis/stack-alloc.d.ts +20 -0
- package/dist/ir/backend/bytecode-emitter.d.ts +237 -0
- package/dist/ir/backend/bytecode-vm.d.ts +74 -0
- package/dist/ir/backend/emitter.d.ts +121 -0
- package/dist/ir/backend/handles.d.ts +133 -0
- package/dist/ir/backend/legality.d.ts +9 -0
- package/dist/ir/backend/linear-emitter.d.ts +41 -0
- package/dist/ir/backend/wasmgc-emitter.d.ts +43 -0
- package/dist/ir/builder.d.ts +401 -0
- package/dist/ir/from-ast.d.ts +192 -0
- package/dist/ir/index.d.ts +16 -0
- package/dist/ir/integration.d.ts +27 -0
- package/dist/ir/lower.d.ts +203 -0
- package/dist/ir/nodes.d.ts +1452 -0
- package/dist/ir/passes/alloc-discipline.d.ts +19 -0
- package/dist/ir/passes/constant-fold.d.ts +7 -0
- package/dist/ir/passes/dead-code.d.ts +18 -0
- package/dist/ir/passes/inline-small.d.ts +7 -0
- package/dist/ir/passes/monomorphize.d.ts +21 -0
- package/dist/ir/passes/simplify-cfg.d.ts +19 -0
- package/dist/ir/passes/tagged-union-types.d.ts +45 -0
- package/dist/ir/passes/tagged-unions.d.ts +22 -0
- package/dist/ir/propagate.d.ts +135 -0
- package/dist/ir/select.d.ts +81 -0
- package/dist/ir/types.d.ts +832 -0
- package/dist/ir/verify-alloc.d.ts +18 -0
- package/dist/ir/verify.d.ts +7 -0
- package/dist/link/index.d.ts +11 -0
- package/dist/link/isolation.d.ts +24 -0
- package/dist/link/linker.d.ts +37 -0
- package/dist/link/reader.d.ts +158 -0
- package/dist/link/resolver.d.ts +19 -0
- package/dist/optimize.d.ts +54 -0
- package/dist/optimize.js +262 -0
- package/dist/position-map.d.ts +64 -0
- package/dist/process-stdin-prelude.d.ts +16 -0
- package/dist/resolve.d.ts +82 -0
- package/dist/runtime/builtins.d.ts +1 -0
- package/dist/runtime-C-4q_KwU.js +164438 -0
- package/dist/runtime-containment.d.ts +6 -0
- package/dist/runtime-eval.d.ts +132 -0
- package/dist/runtime-instantiate.d.ts +16 -0
- package/dist/runtime.d.ts +128 -0
- package/dist/runtime.js +12 -0
- package/dist/shape-inference.d.ts +20 -0
- package/dist/treeshake.d.ts +17 -0
- package/dist/ts-api.d.ts +30 -0
- package/dist/wit-generator.d.ts +18 -0
- package/package.json +187 -0
|
@@ -0,0 +1,1452 @@
|
|
|
1
|
+
import { ValType } from './types.js';
|
|
2
|
+
export interface IrFuncRef {
|
|
3
|
+
readonly kind: "func";
|
|
4
|
+
/** Unique function name (same namespace as `ctx.funcMap`). */
|
|
5
|
+
readonly name: string;
|
|
6
|
+
}
|
|
7
|
+
export interface IrGlobalRef {
|
|
8
|
+
readonly kind: "global";
|
|
9
|
+
/** Unique global name (same namespace as `ctx.globalMap` or similar). */
|
|
10
|
+
readonly name: string;
|
|
11
|
+
}
|
|
12
|
+
export interface IrTypeRef {
|
|
13
|
+
readonly kind: "type";
|
|
14
|
+
/** Unique WasmGC type name (same namespace as `ctx.typeNames`). */
|
|
15
|
+
readonly name: string;
|
|
16
|
+
}
|
|
17
|
+
export type IrSymRef = IrFuncRef | IrGlobalRef | IrTypeRef;
|
|
18
|
+
/**
|
|
19
|
+
* A canonical object shape — a sorted list of named fields with their IR
|
|
20
|
+
* types. Equal shapes (same names, same types in the same canonical order)
|
|
21
|
+
* resolve to the same WasmGC struct via the lowerer's resolver. Carrying
|
|
22
|
+
* the field types as `IrType` (not `ValType`) lets a struct-of-string or
|
|
23
|
+
* struct-of-object compose cleanly: the resolver recursively materializes
|
|
24
|
+
* field types when registering the WasmGC struct.
|
|
25
|
+
*
|
|
26
|
+
* Names must be unique. The constructor in `from-ast.ts` sorts by name
|
|
27
|
+
* before constructing the IrType so structurally-identical shapes compare
|
|
28
|
+
* equal regardless of source order.
|
|
29
|
+
*/
|
|
30
|
+
export interface IrObjectShape {
|
|
31
|
+
readonly fields: readonly {
|
|
32
|
+
readonly name: string;
|
|
33
|
+
readonly type: IrType;
|
|
34
|
+
}[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Slice 3 (#1169c) — a closure's caller-visible signature. Used both as
|
|
38
|
+
* the IR-level type discriminator for closure values and as the resolver
|
|
39
|
+
* lookup key for the supertype struct + lifted func type. The implicit
|
|
40
|
+
* `__self` struct param at index 0 of the lifted body is NOT present in
|
|
41
|
+
* `params` — it's added by the resolver when synthesizing the func type.
|
|
42
|
+
*/
|
|
43
|
+
export interface IrClosureSignature {
|
|
44
|
+
readonly params: readonly IrType[];
|
|
45
|
+
readonly returnType: IrType;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Slice 4 (#1169d) — descriptor for one field on a class.
|
|
49
|
+
*/
|
|
50
|
+
export interface IrClassFieldDescriptor {
|
|
51
|
+
readonly name: string;
|
|
52
|
+
readonly type: IrType;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Slice 4 (#1169d) — descriptor for one instance method on a class. The
|
|
56
|
+
* implicit `this` receiver is NOT listed in `params` — the lowerer
|
|
57
|
+
* prepends it when emitting the call. A void method has
|
|
58
|
+
* `returnType: null`.
|
|
59
|
+
*/
|
|
60
|
+
export interface IrClassMethodDescriptor {
|
|
61
|
+
readonly name: string;
|
|
62
|
+
readonly params: readonly IrType[];
|
|
63
|
+
readonly returnType: IrType | null;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Slice 4 (#1169d) — symbolic descriptor for a class declared in the
|
|
67
|
+
* compilation unit. Carries the structural info the IR builder needs to
|
|
68
|
+
* type-check `new`/field-access/method-call expressions on instances of
|
|
69
|
+
* this class without consulting the lowering resolver.
|
|
70
|
+
*
|
|
71
|
+
* - `className` unique discriminator (one class per name per unit)
|
|
72
|
+
* - `fields` user fields in canonical order (alphabetical)
|
|
73
|
+
* — the lowerer maps each field `name` to a Wasm
|
|
74
|
+
* struct field index via `resolveClass`, which knows
|
|
75
|
+
* about the legacy `__tag` prefix at field 0.
|
|
76
|
+
* - `methods` instance methods with caller-visible signatures.
|
|
77
|
+
* Static methods are out of slice 4 scope and are
|
|
78
|
+
* not listed.
|
|
79
|
+
* - `constructorParams` user-visible param list for `new C(...)`.
|
|
80
|
+
*
|
|
81
|
+
* Class methods themselves are NOT IR-claimable in slice 4 — they remain
|
|
82
|
+
* on the legacy class-bodies path. The IR only references them by name
|
|
83
|
+
* (`<className>_<methodName>`) at call-site lowering, where the resolver
|
|
84
|
+
* maps the name to the legacy-allocated funcIdx.
|
|
85
|
+
*/
|
|
86
|
+
export interface IrClassShape {
|
|
87
|
+
readonly className: string;
|
|
88
|
+
readonly fields: readonly IrClassFieldDescriptor[];
|
|
89
|
+
readonly methods: readonly IrClassMethodDescriptor[];
|
|
90
|
+
readonly constructorParams: readonly IrType[];
|
|
91
|
+
}
|
|
92
|
+
export type IrType = {
|
|
93
|
+
readonly kind: "val";
|
|
94
|
+
readonly val: ValType;
|
|
95
|
+
readonly signed?: boolean;
|
|
96
|
+
} | {
|
|
97
|
+
readonly kind: "string";
|
|
98
|
+
} | {
|
|
99
|
+
readonly kind: "object";
|
|
100
|
+
readonly shape: IrObjectShape;
|
|
101
|
+
} | {
|
|
102
|
+
readonly kind: "closure";
|
|
103
|
+
readonly signature: IrClosureSignature;
|
|
104
|
+
} | {
|
|
105
|
+
readonly kind: "class";
|
|
106
|
+
readonly shape: IrClassShape;
|
|
107
|
+
} | {
|
|
108
|
+
readonly kind: "extern";
|
|
109
|
+
readonly className: string;
|
|
110
|
+
} | {
|
|
111
|
+
readonly kind: "union";
|
|
112
|
+
readonly members: readonly IrType[];
|
|
113
|
+
} | {
|
|
114
|
+
readonly kind: "boxed";
|
|
115
|
+
readonly inner: IrType;
|
|
116
|
+
};
|
|
117
|
+
/** Wrap a plain ValType as an IrType — the common path for Phase 1/2 callers. */
|
|
118
|
+
export declare function irVal(v: ValType): IrType;
|
|
119
|
+
/**
|
|
120
|
+
* Wrap a ValType as an IrType with an explicit signedness fact (#1126 Stage 1).
|
|
121
|
+
* Use this only for `i32` ValTypes where the value-domain (signed `int32` vs
|
|
122
|
+
* unsigned `uint32`) is known. For non-i32 ValTypes the `signed` flag is
|
|
123
|
+
* meaningless; callers should use `irVal()` instead.
|
|
124
|
+
*
|
|
125
|
+
* The flag is read by Stage 3 emit decisions (signed vs unsigned shifts,
|
|
126
|
+
* comparisons, conversions back to f64). For Stage 1 it is purely additive —
|
|
127
|
+
* no existing emitter consults it yet.
|
|
128
|
+
*/
|
|
129
|
+
export declare function irValSigned(v: ValType, signed: boolean): IrType;
|
|
130
|
+
/**
|
|
131
|
+
* Return the single underlying ValType for a `val`-kind IrType, else `null`.
|
|
132
|
+
* Call sites that previously did `t.kind === "f64"` against an `IrType` now
|
|
133
|
+
* do `asVal(t)?.kind === "f64"`.
|
|
134
|
+
*/
|
|
135
|
+
export declare function asVal(t: IrType): ValType | null;
|
|
136
|
+
/**
|
|
137
|
+
* Structural equality for IrType. Two types are equal iff they have the same
|
|
138
|
+
* shape and their underlying ValType members compare structurally equal.
|
|
139
|
+
*
|
|
140
|
+
* Used by the verifier and by migration assertions. We keep the implementation
|
|
141
|
+
* local to avoid pulling a full deep-equal dep into the IR layer.
|
|
142
|
+
*/
|
|
143
|
+
export declare function irTypeEquals(a: IrType, b: IrType): boolean;
|
|
144
|
+
/**
|
|
145
|
+
* Slice 4 (#1169d): structural equality for class shapes. `className` is
|
|
146
|
+
* the discriminator — every class is unique within a compilation unit, so
|
|
147
|
+
* two `IrClassShape` values with the same `className` represent the same
|
|
148
|
+
* class. We don't recurse into `fields` / `methods` / `constructorParams`
|
|
149
|
+
* because they're a deterministic projection of `className` (one
|
|
150
|
+
* declaration per class per unit). Cross-unit class types are out of
|
|
151
|
+
* slice 4 scope.
|
|
152
|
+
*/
|
|
153
|
+
export declare function classShapeEquals(a: IrClassShape, b: IrClassShape): boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Structural equality for closure signatures. Recurses through param /
|
|
156
|
+
* return IrTypes via `irTypeEquals` so a closure-of-closure or a
|
|
157
|
+
* closure-of-object compares correctly.
|
|
158
|
+
*/
|
|
159
|
+
export declare function closureSignatureEquals(a: IrClosureSignature, b: IrClosureSignature): boolean;
|
|
160
|
+
/**
|
|
161
|
+
* Structural equality for object shapes. Field lists must be parallel
|
|
162
|
+
* (same length, same order, same name and IrType per slot). Recursing
|
|
163
|
+
* via `irTypeEquals` lets nested object fields compare correctly.
|
|
164
|
+
*/
|
|
165
|
+
export declare function objectShapeEquals(a: IrObjectShape, b: IrObjectShape): boolean;
|
|
166
|
+
/**
|
|
167
|
+
* An SSA value ID — uniquely identifies one defining instruction or block arg
|
|
168
|
+
* within one IrFunction. Values are NOT shared across functions.
|
|
169
|
+
*
|
|
170
|
+
* Represented as a branded number for cheap comparison + map-key use. `-1`
|
|
171
|
+
* is reserved as an intentionally invalid sentinel and must never appear in
|
|
172
|
+
* an emitted IR graph.
|
|
173
|
+
*/
|
|
174
|
+
export type IrValueId = number & {
|
|
175
|
+
readonly __brand: "IrValueId";
|
|
176
|
+
};
|
|
177
|
+
export declare function asValueId(n: number): IrValueId;
|
|
178
|
+
/**
|
|
179
|
+
* Stable identity of an allocation site (#1586).
|
|
180
|
+
*
|
|
181
|
+
* Unlike {@link IrValueId} — which is a per-function SSA index that inlining
|
|
182
|
+
* and monomorphization renumber — an `AllocSiteId` is **module-global** and
|
|
183
|
+
* travels on the instruction itself (`IrInstrBase.alloc`). It survives every
|
|
184
|
+
* IR transformation: passes preserve it through value-preserving rewrites,
|
|
185
|
+
* alias it through fusion, and retire it on deletion (see the pass-discipline
|
|
186
|
+
* rules in docs/adr/0013-ir-allocation-sites.md).
|
|
187
|
+
*
|
|
188
|
+
* Identity MUST NOT be keyed on `IrValueId` — that breaks under renumbering.
|
|
189
|
+
*/
|
|
190
|
+
export type AllocSiteId = number & {
|
|
191
|
+
readonly __brand: "AllocSiteId";
|
|
192
|
+
};
|
|
193
|
+
export declare function asAllocSiteId(n: number): AllocSiteId;
|
|
194
|
+
/**
|
|
195
|
+
* The category of value an allocation site brings into existence. Mirrors the
|
|
196
|
+
* value-creating IR instr kinds (object.new, closure.new, …). Black-box
|
|
197
|
+
* built-in internal allocations are out of scope (#1586 non-goals).
|
|
198
|
+
*/
|
|
199
|
+
export type AllocKind = "object" | "array" | "string" | "closure" | "refcell" | "box" | "extern" | "iterator" | "generator";
|
|
200
|
+
/** Allocate sequential IrValueIds within a function. */
|
|
201
|
+
export declare class IrValueIdAllocator {
|
|
202
|
+
private next;
|
|
203
|
+
fresh(): IrValueId;
|
|
204
|
+
get count(): number;
|
|
205
|
+
}
|
|
206
|
+
export type IrConst = {
|
|
207
|
+
readonly kind: "i32";
|
|
208
|
+
readonly value: number;
|
|
209
|
+
} | {
|
|
210
|
+
readonly kind: "i64";
|
|
211
|
+
readonly value: bigint;
|
|
212
|
+
} | {
|
|
213
|
+
readonly kind: "f32";
|
|
214
|
+
readonly value: number;
|
|
215
|
+
} | {
|
|
216
|
+
readonly kind: "f64";
|
|
217
|
+
readonly value: number;
|
|
218
|
+
} | {
|
|
219
|
+
readonly kind: "bool";
|
|
220
|
+
readonly value: boolean;
|
|
221
|
+
} | {
|
|
222
|
+
readonly kind: "null";
|
|
223
|
+
readonly ty: IrType;
|
|
224
|
+
} | {
|
|
225
|
+
readonly kind: "undefined";
|
|
226
|
+
};
|
|
227
|
+
export interface IrSiteId {
|
|
228
|
+
readonly line: number;
|
|
229
|
+
readonly column: number;
|
|
230
|
+
}
|
|
231
|
+
export interface IrInstrBase {
|
|
232
|
+
/** SSA def produced by this instr. `null` for void instrs. */
|
|
233
|
+
readonly result: IrValueId | null;
|
|
234
|
+
/** Static type of the result, if any. Redundant w/ `result`'s type but kept local for verifier speed. */
|
|
235
|
+
readonly resultType: IrType | null;
|
|
236
|
+
/** Source location for diagnostics. Optional in Phase 1. */
|
|
237
|
+
readonly site?: IrSiteId;
|
|
238
|
+
/**
|
|
239
|
+
* Stable allocation-site identity (#1586). Present iff this instr is a
|
|
240
|
+
* value-creating (allocation) site — see {@link AllocKind} and the audit
|
|
241
|
+
* table in docs/adr/0013-ir-allocation-sites.md. Distinct from `result`
|
|
242
|
+
* (an `IrValueId`, which inlining/monomorphize renumber). Inert at
|
|
243
|
+
* lowering, so the emitted Wasm is byte-identical whether or not it is set.
|
|
244
|
+
*/
|
|
245
|
+
readonly alloc?: AllocSiteId;
|
|
246
|
+
}
|
|
247
|
+
/** Materialize a constant into an SSA value. */
|
|
248
|
+
export interface IrInstrConst extends IrInstrBase {
|
|
249
|
+
readonly kind: "const";
|
|
250
|
+
readonly value: IrConst;
|
|
251
|
+
}
|
|
252
|
+
/** Call a function by symbolic reference. Return value (if any) is `result`. */
|
|
253
|
+
export interface IrInstrCall extends IrInstrBase {
|
|
254
|
+
readonly kind: "call";
|
|
255
|
+
readonly target: IrFuncRef;
|
|
256
|
+
readonly args: readonly IrValueId[];
|
|
257
|
+
}
|
|
258
|
+
/** Read a global by symbolic reference. */
|
|
259
|
+
export interface IrInstrGlobalGet extends IrInstrBase {
|
|
260
|
+
readonly kind: "global.get";
|
|
261
|
+
readonly target: IrGlobalRef;
|
|
262
|
+
}
|
|
263
|
+
/** Write a global by symbolic reference. Void-result. */
|
|
264
|
+
export interface IrInstrGlobalSet extends IrInstrBase {
|
|
265
|
+
readonly kind: "global.set";
|
|
266
|
+
readonly target: IrGlobalRef;
|
|
267
|
+
readonly value: IrValueId;
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Typed binary primitive. The `op` tag encodes both operand type(s) and the
|
|
271
|
+
* operation, so the lowerer can map 1:1 to a Wasm instruction without
|
|
272
|
+
* re-inferring types. Phase 1 covers the numeric/bool subset.
|
|
273
|
+
*/
|
|
274
|
+
export type IrBinop = "f64.add" | "f64.sub" | "f64.mul" | "f64.div" | "f64.eq" | "f64.ne" | "f64.lt" | "f64.le" | "f64.gt" | "f64.ge" | "i32.eq" | "i32.ne" | "i32.and" | "i32.or" | "i32.lt_s" | "i32.le_s" | "i32.gt_s" | "i32.ge_s" | "i32.lt_u" | "i32.le_u" | "i32.gt_u" | "i32.ge_u" | "js.bitand" | "js.bitor" | "js.bitxor" | "js.shl" | "js.shr_s" | "js.shr_u";
|
|
275
|
+
/**
|
|
276
|
+
* Typed unary primitive. `f64.neg` negates a number. `i32.eqz` implements
|
|
277
|
+
* bool negation (`!x` where x is bool — 0↔1).
|
|
278
|
+
*
|
|
279
|
+
* Slice 12 (#1169o) adds `i32.trunc_sat_f64_s` — saturating f64 → i32
|
|
280
|
+
* truncation. Used to convert a JS-style f64 array index into the i32
|
|
281
|
+
* the backend `vec.get` instruction expects. Saturation handles
|
|
282
|
+
* NaN→0 and out-of-range values gracefully (no trap), matching what
|
|
283
|
+
* test262's array-indexing patterns expect.
|
|
284
|
+
*/
|
|
285
|
+
export type IrUnop = "f64.neg" | "i32.eqz" | "i32.trunc_sat_f64_s" | "f64.abs" | "f64.sqrt" | "f64.floor" | "f64.ceil" | "f64.trunc" | "ref.is_null";
|
|
286
|
+
export interface IrInstrBinary extends IrInstrBase {
|
|
287
|
+
readonly kind: "binary";
|
|
288
|
+
readonly op: IrBinop;
|
|
289
|
+
readonly lhs: IrValueId;
|
|
290
|
+
readonly rhs: IrValueId;
|
|
291
|
+
}
|
|
292
|
+
export interface IrInstrUnary extends IrInstrBase {
|
|
293
|
+
readonly kind: "unary";
|
|
294
|
+
readonly op: IrUnop;
|
|
295
|
+
readonly rand: IrValueId;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Conditional expression — lowers to Wasm `select`. Both arms are evaluated;
|
|
299
|
+
* this is safe for pure Phase 1 expressions (no calls, no side effects).
|
|
300
|
+
* Branching control flow (for statements with side effects) comes in Phase 2
|
|
301
|
+
* via `br_if` terminators.
|
|
302
|
+
*/
|
|
303
|
+
export interface IrInstrSelect extends IrInstrBase {
|
|
304
|
+
readonly kind: "select";
|
|
305
|
+
readonly condition: IrValueId;
|
|
306
|
+
readonly whenTrue: IrValueId;
|
|
307
|
+
readonly whenFalse: IrValueId;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* (#1392) Value-producing if/else expression. UNLIKE `select`, this
|
|
311
|
+
* SHORT-CIRCUITS — only one branch's instructions are executed. Used by
|
|
312
|
+
* the optional-chain lowering (`recv?.prop`) where the right-hand side
|
|
313
|
+
* (`recv.prop`) MUST NOT execute when `recv` is null.
|
|
314
|
+
*
|
|
315
|
+
* The two arm buffers (`then` / `else`) are self-contained instruction
|
|
316
|
+
* lists collected via `IrFunctionBuilder.collectBodyInstrs(...)`. They
|
|
317
|
+
* may reference SSA values defined OUTSIDE the if-instr (those are
|
|
318
|
+
* available through Wasm locals), but values defined INSIDE one arm are
|
|
319
|
+
* NOT visible to the other arm or to instructions following the if.
|
|
320
|
+
*
|
|
321
|
+
* The carrier values are `thenValue` / `elseValue` — IrValueIds defined
|
|
322
|
+
* inside the corresponding arm. The lowerer emits a Wasm
|
|
323
|
+
* `if (result T) ... else ... end` block where each arm leaves its
|
|
324
|
+
* carrier value on the stack; the post-block `local.set` binds the
|
|
325
|
+
* result to the if-instr's `result` SSA value.
|
|
326
|
+
*
|
|
327
|
+
* Both arms must produce values of `resultType`. The verifier rejects
|
|
328
|
+
* shape mismatches.
|
|
329
|
+
*/
|
|
330
|
+
export interface IrInstrIf extends IrInstrBase {
|
|
331
|
+
readonly kind: "if";
|
|
332
|
+
readonly cond: IrValueId;
|
|
333
|
+
readonly then: readonly IrInstr[];
|
|
334
|
+
readonly thenValue: IrValueId;
|
|
335
|
+
readonly else: readonly IrInstr[];
|
|
336
|
+
readonly elseValue: IrValueId;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* (#1373 Phase B) `await <expr>` — suspend the current async function until
|
|
340
|
+
* `expr`'s Promise settles, then resume with the resolved value. The IR
|
|
341
|
+
* node carries the operand whose evaluation produces a Promise (or a
|
|
342
|
+
* non-Promise value that must be wrapped in `Promise.resolve` before
|
|
343
|
+
* suspension per spec §27.2.1.4).
|
|
344
|
+
*
|
|
345
|
+
* Phase B (this slice) defines the type only — no lowering. Phase C
|
|
346
|
+
* (CPS transform, follow-up #1373b) splits the function at each await
|
|
347
|
+
* point, lifts the post-await tail into a continuation closure, and
|
|
348
|
+
* emits microtask-queue calls (`__promise_then(promise, continuation)`)
|
|
349
|
+
* to schedule resumption.
|
|
350
|
+
*
|
|
351
|
+
* The result IrValueId carries the resolved value. Its IrType must
|
|
352
|
+
* match the surrounding expression context (typically the unwrapped
|
|
353
|
+
* `T` from `Promise<T>`).
|
|
354
|
+
*/
|
|
355
|
+
export interface IrInstrAwait extends IrInstrBase {
|
|
356
|
+
readonly kind: "await";
|
|
357
|
+
readonly operand: IrValueId;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* (#1373 Phase B) `return <value>` from an async function body. UNLIKE
|
|
361
|
+
* `IrTerminatorReturn`, which produces the bare value, this wraps the
|
|
362
|
+
* value in `Promise.resolve(value)` per the async function spec
|
|
363
|
+
* §15.8.5.5. The IR node defines the wrap intent; lowering (Phase C)
|
|
364
|
+
* emits the wrap via the existing `Promise_resolve` host import in
|
|
365
|
+
* JS-host mode or via the standalone `$Promise` struct.new in WASI
|
|
366
|
+
* mode (the latter wired in #1326 Phase 1B).
|
|
367
|
+
*
|
|
368
|
+
* Used in tail position only — non-tail `return` inside an async
|
|
369
|
+
* function flows through the IR's normal block terminator, which the
|
|
370
|
+
* Phase C lowerer recognises and routes through the same wrap.
|
|
371
|
+
*/
|
|
372
|
+
export interface IrInstrAsyncReturn extends IrInstrBase {
|
|
373
|
+
readonly kind: "async.return";
|
|
374
|
+
readonly value: IrValueId;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* (#1373 Phase B) Synchronous throw inside an async function body.
|
|
378
|
+
* UNLIKE `IrInstrThrow`, which propagates as a Wasm exception, this
|
|
379
|
+
* wraps the thrown value in `Promise.reject(reason)` so the async
|
|
380
|
+
* function's outer Promise settles in the rejected state. Lowering
|
|
381
|
+
* (Phase C) emits the wrap via `Promise_reject` (host) or `$Promise`
|
|
382
|
+
* struct.new with `state = REJECTED` (standalone, #1326 Phase 1B).
|
|
383
|
+
*
|
|
384
|
+
* Currently NOT emitted by from-ast — Phase C wires it from
|
|
385
|
+
* `ts.ThrowStatement` nodes inside async function bodies.
|
|
386
|
+
*/
|
|
387
|
+
export interface IrInstrAsyncThrow extends IrInstrBase {
|
|
388
|
+
readonly kind: "async.throw";
|
|
389
|
+
readonly reason: IrValueId;
|
|
390
|
+
}
|
|
391
|
+
/**
|
|
392
|
+
* Escape hatch: a raw backend instruction sequence with no SSA structure.
|
|
393
|
+
* Phase 1 uses this as a bridge so we can describe any function without
|
|
394
|
+
* re-encoding the whole Wasm opcode set in IR. Phase 2 will narrow uses.
|
|
395
|
+
* The verifier treats it as an opaque block: stack contract must match.
|
|
396
|
+
*/
|
|
397
|
+
export interface IrInstrRawWasm extends IrInstrBase {
|
|
398
|
+
readonly kind: "raw.wasm";
|
|
399
|
+
/** Backend ops to emit verbatim. */
|
|
400
|
+
readonly ops: readonly import('./types.js').Instr[];
|
|
401
|
+
/** Wasm value-stack delta after running `ops` (positive = pushes). */
|
|
402
|
+
readonly stackDelta: number;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Box a scalar into a tagged-union struct. `toType` must be an `IrType.union`
|
|
406
|
+
* whose `members` contains `value`'s static ValType. Lowering emits
|
|
407
|
+
* `struct.new $union_<members>` with the matching tag constant + the value
|
|
408
|
+
* in the `$val` field. Result is `(ref $union_<members>)` / the `toType`.
|
|
409
|
+
*/
|
|
410
|
+
export interface IrInstrBox extends IrInstrBase {
|
|
411
|
+
readonly kind: "box";
|
|
412
|
+
readonly value: IrValueId;
|
|
413
|
+
readonly toType: IrType;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Unbox a tagged-union value to one of its member ValTypes. The caller must
|
|
417
|
+
* have proved the tag already (via `tag.test` earlier in the same IR path);
|
|
418
|
+
* lowering emits a plain `struct.get $val` without a tag check at runtime.
|
|
419
|
+
* A debug-mode assertion can still verify the tag.
|
|
420
|
+
*/
|
|
421
|
+
export interface IrInstrUnbox extends IrInstrBase {
|
|
422
|
+
readonly kind: "unbox";
|
|
423
|
+
readonly value: IrValueId;
|
|
424
|
+
readonly tag: ValType;
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Runtime tag discriminator — result (via `IrInstrBase.result`) is `i32`,
|
|
428
|
+
* 1 if `value`'s runtime tag matches `tag`, else 0. `value` must be a
|
|
429
|
+
* tagged-union type containing `tag` as a member. Lowers to
|
|
430
|
+
* `struct.get $tag; i32.const <N>; i32.eq`.
|
|
431
|
+
*/
|
|
432
|
+
export interface IrInstrTagTest extends IrInstrBase {
|
|
433
|
+
readonly kind: "tag.test";
|
|
434
|
+
readonly value: IrValueId;
|
|
435
|
+
readonly tag: ValType;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Materialize a string literal as an SSA value of `IrType.string`. The
|
|
439
|
+
* backend representation is determined by `IrLowerResolver.emitStringConst`:
|
|
440
|
+
* - host strings → register a `string_constants.<value>` global import,
|
|
441
|
+
* emit `global.get`.
|
|
442
|
+
* - native → emit inline `array.new_fixed` of the WTF-16 code units,
|
|
443
|
+
* then `struct.new $NativeString`.
|
|
444
|
+
*/
|
|
445
|
+
export interface IrInstrStringConst extends IrInstrBase {
|
|
446
|
+
readonly kind: "string.const";
|
|
447
|
+
/** Raw JS string; the lowerer treats `value.length` as UTF-16 code units. */
|
|
448
|
+
readonly value: string;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Concatenate two strings — the ECMAScript `s1 + s2` operator restricted to
|
|
452
|
+
* the case where both operands are statically known to be strings. Result
|
|
453
|
+
* type: `IrType.string`.
|
|
454
|
+
*/
|
|
455
|
+
export interface IrInstrStringConcat extends IrInstrBase {
|
|
456
|
+
readonly kind: "string.concat";
|
|
457
|
+
readonly lhs: IrValueId;
|
|
458
|
+
readonly rhs: IrValueId;
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* String equality. `===` and `!==` are both modeled via this single instr —
|
|
462
|
+
* `negate: true` ↔ `!==`. Result type: `i32` (bool).
|
|
463
|
+
*/
|
|
464
|
+
export interface IrInstrStringEq extends IrInstrBase {
|
|
465
|
+
readonly kind: "string.eq";
|
|
466
|
+
readonly lhs: IrValueId;
|
|
467
|
+
readonly rhs: IrValueId;
|
|
468
|
+
readonly negate: boolean;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* String length — corresponds to the JS `s.length` property access. Despite
|
|
472
|
+
* the underlying Wasm op returning `i32`, the IR result is `f64` to match
|
|
473
|
+
* JS Number semantics, so consumers can compose with the rest of the
|
|
474
|
+
* numeric IR without an extra coercion step. Lowering inserts the
|
|
475
|
+
* `f64.convert_i32_s` after the backend's length op.
|
|
476
|
+
*/
|
|
477
|
+
export interface IrInstrStringLen extends IrInstrBase {
|
|
478
|
+
readonly kind: "string.len";
|
|
479
|
+
readonly value: IrValueId;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Materialize an object literal as a WasmGC struct. `shape` declares the
|
|
483
|
+
* struct's field layout (already canonically sorted by name); `values` is
|
|
484
|
+
* parallel to `shape.fields` and must have the same length. Lowering emits
|
|
485
|
+
* each value in canonical order followed by `struct.new $obj_<shape>`.
|
|
486
|
+
*
|
|
487
|
+
* Result type: `{ kind: "object", shape }`.
|
|
488
|
+
*/
|
|
489
|
+
export interface IrInstrObjectNew extends IrInstrBase {
|
|
490
|
+
readonly kind: "object.new";
|
|
491
|
+
readonly shape: IrObjectShape;
|
|
492
|
+
readonly values: readonly IrValueId[];
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Read a named field from an object. `value` must be of `IrType.object`
|
|
496
|
+
* with a shape whose `fields` contain `name`. Lowering emits
|
|
497
|
+
* `struct.get $obj_<shape> <fieldIdx>`.
|
|
498
|
+
*
|
|
499
|
+
* Result type: the field's IrType (must match `resultType`).
|
|
500
|
+
*/
|
|
501
|
+
export interface IrInstrObjectGet extends IrInstrBase {
|
|
502
|
+
readonly kind: "object.get";
|
|
503
|
+
readonly value: IrValueId;
|
|
504
|
+
readonly name: string;
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Write a named field on an object. `value` must be `IrType.object`,
|
|
508
|
+
* `newValue` must match the field's IrType. Void result. Lowering emits
|
|
509
|
+
* `struct.set $obj_<shape> <fieldIdx>`.
|
|
510
|
+
*/
|
|
511
|
+
export interface IrInstrObjectSet extends IrInstrBase {
|
|
512
|
+
readonly kind: "object.set";
|
|
513
|
+
readonly value: IrValueId;
|
|
514
|
+
readonly name: string;
|
|
515
|
+
readonly newValue: IrValueId;
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Materialize a closure value. `liftedFunc` names the lifted top-level
|
|
519
|
+
* function (registered in the IR module as a synthesized BuiltFn).
|
|
520
|
+
* `signature` is the caller-visible signature (used to look up the
|
|
521
|
+
* supertype struct + funcref type). `captures` populates the subtype's
|
|
522
|
+
* capture fields parallel to `captureFieldTypes`.
|
|
523
|
+
*
|
|
524
|
+
* Lowering emits:
|
|
525
|
+
* ref.func $lifted
|
|
526
|
+
* <push each capture>
|
|
527
|
+
* struct.new $closure_<signature>_<captureSig>
|
|
528
|
+
*
|
|
529
|
+
* Result type: `{ kind: "closure"; signature }`. The Wasm-level value
|
|
530
|
+
* type is the supertype struct so call_ref against the base func type
|
|
531
|
+
* accepts any subtype.
|
|
532
|
+
*/
|
|
533
|
+
export interface IrInstrClosureNew extends IrInstrBase {
|
|
534
|
+
readonly kind: "closure.new";
|
|
535
|
+
readonly liftedFunc: IrFuncRef;
|
|
536
|
+
readonly signature: IrClosureSignature;
|
|
537
|
+
/** Capture-field IrTypes in struct field order (post-funcref). */
|
|
538
|
+
readonly captureFieldTypes: readonly IrType[];
|
|
539
|
+
/** SSA values populating the capture fields, parallel to captureFieldTypes. */
|
|
540
|
+
readonly captures: readonly IrValueId[];
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Read a capture field from the implicit `__self` closure struct. Only
|
|
544
|
+
* valid inside a lifted closure body whose IrFunction carries
|
|
545
|
+
* `closureSubtype` metadata. `index` is the 0-based capture position
|
|
546
|
+
* (post-funcref).
|
|
547
|
+
*
|
|
548
|
+
* Lowering emits:
|
|
549
|
+
* <self>
|
|
550
|
+
* ref.cast $self_subtype
|
|
551
|
+
* struct.get $self_subtype (index+1)
|
|
552
|
+
*/
|
|
553
|
+
export interface IrInstrClosureCap extends IrInstrBase {
|
|
554
|
+
readonly kind: "closure.cap";
|
|
555
|
+
/** SSA value of the closure-typed __self param (the lifted func's param 0). */
|
|
556
|
+
readonly self: IrValueId;
|
|
557
|
+
readonly index: number;
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Invoke a closure value. `callee` must be `IrType.closure`. `args` must
|
|
561
|
+
* match the signature's params arity and types.
|
|
562
|
+
*
|
|
563
|
+
* Lowering emits:
|
|
564
|
+
* <emit callee> ;; pushes self
|
|
565
|
+
* <emit args>
|
|
566
|
+
* <emit callee> ;; pushes self again — second use forces a Wasm local
|
|
567
|
+
* struct.get $base_struct $func
|
|
568
|
+
* call_ref $base_funcType
|
|
569
|
+
*
|
|
570
|
+
* Result type: `signature.returnType`.
|
|
571
|
+
*/
|
|
572
|
+
export interface IrInstrClosureCall extends IrInstrBase {
|
|
573
|
+
readonly kind: "closure.call";
|
|
574
|
+
readonly callee: IrValueId;
|
|
575
|
+
readonly args: readonly IrValueId[];
|
|
576
|
+
}
|
|
577
|
+
/**
|
|
578
|
+
* Wrap a primitive value in a fresh ref cell. Lowering:
|
|
579
|
+
* <emit value>
|
|
580
|
+
* struct.new $refcell_<inner>
|
|
581
|
+
*
|
|
582
|
+
* Result type: `{ kind: "boxed"; inner: <ValType of value> }`.
|
|
583
|
+
*/
|
|
584
|
+
export interface IrInstrRefCellNew extends IrInstrBase {
|
|
585
|
+
readonly kind: "refcell.new";
|
|
586
|
+
readonly value: IrValueId;
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Read the inner value out of a ref cell. `cell` must be `IrType.boxed`.
|
|
590
|
+
* Result type is `irVal(cell.inner)`.
|
|
591
|
+
*
|
|
592
|
+
* Lowering: `<emit cell>; struct.get $refcell 0`.
|
|
593
|
+
*/
|
|
594
|
+
export interface IrInstrRefCellGet extends IrInstrBase {
|
|
595
|
+
readonly kind: "refcell.get";
|
|
596
|
+
readonly cell: IrValueId;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Write a new value through a ref cell. `cell` must be `IrType.boxed`,
|
|
600
|
+
* `value` ValType must equal `cell.inner`. Void result.
|
|
601
|
+
*
|
|
602
|
+
* Lowering: `<emit cell>; <emit value>; struct.set $refcell 0`.
|
|
603
|
+
*/
|
|
604
|
+
export interface IrInstrRefCellSet extends IrInstrBase {
|
|
605
|
+
readonly kind: "refcell.set";
|
|
606
|
+
readonly cell: IrValueId;
|
|
607
|
+
readonly value: IrValueId;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Construct a class instance via the legacy-registered constructor.
|
|
611
|
+
*
|
|
612
|
+
* Lowering:
|
|
613
|
+
* <emit each arg in order>
|
|
614
|
+
* call $<className>_new
|
|
615
|
+
*
|
|
616
|
+
* Result type: `{ kind: "class"; shape }`. The Wasm-level value type is
|
|
617
|
+
* `(ref $ClassStruct)` (non-null) — `<className>_new` is registered with
|
|
618
|
+
* a non-null ref result by `collectClassDeclaration`.
|
|
619
|
+
*/
|
|
620
|
+
export interface IrInstrClassNew extends IrInstrBase {
|
|
621
|
+
readonly kind: "class.new";
|
|
622
|
+
readonly shape: IrClassShape;
|
|
623
|
+
readonly args: readonly IrValueId[];
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Read a named field from a class instance. `value` must be `IrType.class`
|
|
627
|
+
* with a shape containing `fieldName`. Lowering emits:
|
|
628
|
+
* <emit value>
|
|
629
|
+
* struct.get $<className> <wasmFieldIdx>
|
|
630
|
+
*
|
|
631
|
+
* The wasm field index accounts for the legacy `__tag` prefix at field 0
|
|
632
|
+
* — see `IrLowerResolver.resolveClass`.
|
|
633
|
+
*
|
|
634
|
+
* Result type: the field's IrType (also placed in `resultType`).
|
|
635
|
+
*/
|
|
636
|
+
export interface IrInstrClassGet extends IrInstrBase {
|
|
637
|
+
readonly kind: "class.get";
|
|
638
|
+
readonly value: IrValueId;
|
|
639
|
+
readonly fieldName: string;
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Write a named field on a class instance. Void result. Lowering emits:
|
|
643
|
+
* <emit value>
|
|
644
|
+
* <emit newValue>
|
|
645
|
+
* struct.set $<className> <wasmFieldIdx>
|
|
646
|
+
*
|
|
647
|
+
* The legacy `collectClassDeclaration` pass widens all class fields to
|
|
648
|
+
* `mutable: true`, so `struct.set` is always valid.
|
|
649
|
+
*/
|
|
650
|
+
export interface IrInstrClassSet extends IrInstrBase {
|
|
651
|
+
readonly kind: "class.set";
|
|
652
|
+
readonly value: IrValueId;
|
|
653
|
+
readonly fieldName: string;
|
|
654
|
+
readonly newValue: IrValueId;
|
|
655
|
+
}
|
|
656
|
+
/**
|
|
657
|
+
* Invoke an instance method. `receiver` must be `IrType.class` whose
|
|
658
|
+
* shape contains `methodName`. The implicit `this` is prepended as the
|
|
659
|
+
* first call argument. Lowering emits:
|
|
660
|
+
* <emit receiver>
|
|
661
|
+
* <emit each arg in order>
|
|
662
|
+
* call $<className>_<methodName>
|
|
663
|
+
*
|
|
664
|
+
* Result type: the method descriptor's `returnType`. A void method has
|
|
665
|
+
* `result: null` and `resultType: null`; the AST→IR lowerer rejects
|
|
666
|
+
* such calls in expression position so we never see a void method as
|
|
667
|
+
* `lowerExpr` output.
|
|
668
|
+
*/
|
|
669
|
+
export interface IrInstrClassCall extends IrInstrBase {
|
|
670
|
+
readonly kind: "class.call";
|
|
671
|
+
readonly receiver: IrValueId;
|
|
672
|
+
readonly methodName: string;
|
|
673
|
+
readonly args: readonly IrValueId[];
|
|
674
|
+
}
|
|
675
|
+
/**
|
|
676
|
+
* Read a Wasm-local slot. `index` is the function-level slot index assigned
|
|
677
|
+
* at IR build time (allocated via `IrFunctionBuilder.declareSlot`). The slot's
|
|
678
|
+
* declared type must be a primitive ValType; the result IrType is `irVal`
|
|
679
|
+
* of that ValType.
|
|
680
|
+
*
|
|
681
|
+
* Lowering: `local.get <slotIndex>`.
|
|
682
|
+
*/
|
|
683
|
+
export interface IrInstrSlotRead extends IrInstrBase {
|
|
684
|
+
readonly kind: "slot.read";
|
|
685
|
+
readonly slotIndex: number;
|
|
686
|
+
}
|
|
687
|
+
/**
|
|
688
|
+
* Write a value to a Wasm-local slot. The value's IrType must be `val` with
|
|
689
|
+
* a ValType matching the slot's declared type. Void result.
|
|
690
|
+
*
|
|
691
|
+
* Lowering: `<emit value>; local.set <slotIndex>`.
|
|
692
|
+
*/
|
|
693
|
+
export interface IrInstrSlotWrite extends IrInstrBase {
|
|
694
|
+
readonly kind: "slot.write";
|
|
695
|
+
readonly slotIndex: number;
|
|
696
|
+
readonly value: IrValueId;
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Read `vec.length` (i32) from a vec struct. The vec must have an IrType
|
|
700
|
+
* that the lowerer's resolver recognises as a vec (typeIdx with a layout of
|
|
701
|
+
* `{ length: i32, data: (ref $arr) }`). Result is f64 (matching JS Number
|
|
702
|
+
* semantics — same approach as `string.len`); lowering inserts the
|
|
703
|
+
* `f64.convert_i32_s` after the i32 read.
|
|
704
|
+
*/
|
|
705
|
+
export interface IrInstrVecLen extends IrInstrBase {
|
|
706
|
+
readonly kind: "vec.len";
|
|
707
|
+
readonly vec: IrValueId;
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Index into a vec struct's data array. `index` must be an SSA value of
|
|
711
|
+
* IrType `irVal({ kind: "i32" })` (f64-to-i32 conversion happens at the
|
|
712
|
+
* caller — for-of always uses an i32 counter so this is always already i32).
|
|
713
|
+
*
|
|
714
|
+
* `resultType` carries the vec element's IrType (the lowerer matches it
|
|
715
|
+
* against the vec struct's data array's element type).
|
|
716
|
+
*
|
|
717
|
+
* Lowering: `<emit vec>; struct.get $vec data; <emit index>; array.get $arr`.
|
|
718
|
+
*/
|
|
719
|
+
export interface IrInstrVecGet extends IrInstrBase {
|
|
720
|
+
readonly kind: "vec.get";
|
|
721
|
+
readonly vec: IrValueId;
|
|
722
|
+
readonly index: IrValueId;
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* #1804 — Construct a vec from a fixed, statically-known set of element SSA
|
|
726
|
+
* values. All `elements` share the IrType `elementType` (the from-ast lowerer
|
|
727
|
+
* coerces each element to this type before emitting). `resultType` is the vec
|
|
728
|
+
* ref IrType (a `ref` to the registered vec struct for `elementType`).
|
|
729
|
+
*
|
|
730
|
+
* Lowering (WasmGC): push e0…eN, `array.new_fixed $arr N`, stash the data ref
|
|
731
|
+
* in a scratch local, push `i32.const N` (length, field 0), re-load the data
|
|
732
|
+
* ref (field 1), `struct.new $vec`. The backend emitter owns the exact op
|
|
733
|
+
* sequence (see `emitVecNewFixed`) so the linear backend can realize the same
|
|
734
|
+
* node over its `[header][len][cap][elements…]` layout.
|
|
735
|
+
*
|
|
736
|
+
* Empty literals (`[]`) carry `elements: []`; the `elementType` is supplied by
|
|
737
|
+
* the from-ast layer from the declared/inferred array type (it cannot be
|
|
738
|
+
* inferred from zero elements).
|
|
739
|
+
*/
|
|
740
|
+
export interface IrInstrVecNewFixed extends IrInstrBase {
|
|
741
|
+
readonly kind: "vec.new_fixed";
|
|
742
|
+
readonly elements: readonly IrValueId[];
|
|
743
|
+
readonly elementType: IrType;
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Statement-level `for (const <bind> of <vec>) <body>` loop instruction.
|
|
747
|
+
*
|
|
748
|
+
* Encodes the array fast path declaratively. The lowerer emits:
|
|
749
|
+
* <emit vec>
|
|
750
|
+
* local.set <vecSlot>
|
|
751
|
+
* local.get <vecSlot>
|
|
752
|
+
* struct.get $vec data
|
|
753
|
+
* local.set <dataSlot>
|
|
754
|
+
* local.get <vecSlot>
|
|
755
|
+
* struct.get $vec length
|
|
756
|
+
* local.set <lenSlot>
|
|
757
|
+
* i32.const 0
|
|
758
|
+
* local.set <counterSlot>
|
|
759
|
+
* block
|
|
760
|
+
* loop
|
|
761
|
+
* local.get <counterSlot>
|
|
762
|
+
* local.get <lenSlot>
|
|
763
|
+
* i32.ge_s
|
|
764
|
+
* br_if 1 ;; exit loop
|
|
765
|
+
* local.get <dataSlot>
|
|
766
|
+
* local.get <counterSlot>
|
|
767
|
+
* array.get $arr
|
|
768
|
+
* local.set <elementSlot>
|
|
769
|
+
* <body instrs>
|
|
770
|
+
* local.get <counterSlot>
|
|
771
|
+
* i32.const 1
|
|
772
|
+
* i32.add
|
|
773
|
+
* local.set <counterSlot>
|
|
774
|
+
* br 0 ;; continue
|
|
775
|
+
* end
|
|
776
|
+
* end
|
|
777
|
+
*
|
|
778
|
+
* The vec must have a non-null ref type pointing to a registered vec struct
|
|
779
|
+
* (the resolver's `resolveVec` resolves it to typeIdx + length/data field
|
|
780
|
+
* indices + element array typeIdx + element ValType). Nullable vec types
|
|
781
|
+
* are not in slice 6 — the selector keeps them on the legacy path.
|
|
782
|
+
*
|
|
783
|
+
* Slot indices are pre-allocated via `IrFunctionBuilder.declareSlot` before
|
|
784
|
+
* the from-ast layer emits this instr.
|
|
785
|
+
*
|
|
786
|
+
* Result: void (`result: null`).
|
|
787
|
+
*/
|
|
788
|
+
export interface IrInstrForOfVec extends IrInstrBase {
|
|
789
|
+
readonly kind: "forof.vec";
|
|
790
|
+
/** SSA value of the iterable. Lowered as the vec ref. */
|
|
791
|
+
readonly vec: IrValueId;
|
|
792
|
+
/** Element type — must match the vec's data array's element ValType. */
|
|
793
|
+
readonly elementType: IrType;
|
|
794
|
+
/** Pre-allocated slot indices (Wasm local indices) for the loop's state. */
|
|
795
|
+
readonly counterSlot: number;
|
|
796
|
+
readonly lengthSlot: number;
|
|
797
|
+
readonly vecSlot: number;
|
|
798
|
+
readonly dataSlot: number;
|
|
799
|
+
readonly elementSlot: number;
|
|
800
|
+
/** Body instrs emitted inside the loop. */
|
|
801
|
+
readonly body: readonly IrInstr[];
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* Coerce a reference-typed IR value to externref. Used by the iterator-
|
|
805
|
+
* protocol arm of `lowerForOfStatement` to feed an arbitrary iterable
|
|
806
|
+
* into the externref-typed `__iterator` host import.
|
|
807
|
+
*
|
|
808
|
+
* The input value must have a reference IrType (val/ref, val/ref_null,
|
|
809
|
+
* val/externref, object, class, closure, or string). Numeric values
|
|
810
|
+
* (i32, f64, etc.) cannot be coerced — the from-ast layer rejects them
|
|
811
|
+
* upstream.
|
|
812
|
+
*
|
|
813
|
+
* Lowering:
|
|
814
|
+
* - val/externref input → no-op (input already externref)
|
|
815
|
+
* - any other ref input → `extern.convert_any` after pushing the value.
|
|
816
|
+
*
|
|
817
|
+
* Result type: `irVal({ kind: "externref" })`.
|
|
818
|
+
*/
|
|
819
|
+
export interface IrInstrCoerceToExternref extends IrInstrBase {
|
|
820
|
+
readonly kind: "coerce.to_externref";
|
|
821
|
+
readonly value: IrValueId;
|
|
822
|
+
}
|
|
823
|
+
/**
|
|
824
|
+
* Slice 7a (#1169f) — push a yielded value onto the generator function's
|
|
825
|
+
* `__gen_buffer` Wasm-local. The lowerer dispatches on the value's IrType:
|
|
826
|
+
* - `irVal({ kind: "f64" })` → `__gen_push_f64(buffer, value)`
|
|
827
|
+
* - (later slices: `i32` → `__gen_push_i32`; `externref` → `__gen_push_ref`)
|
|
828
|
+
*
|
|
829
|
+
* Result is void (`result: null`, `resultType: null`). Only valid inside
|
|
830
|
+
* functions whose `funcKind === "generator"`. The lowerer reads the
|
|
831
|
+
* `IrFunction.generatorBufferSlot` for the `local.get` of the buffer.
|
|
832
|
+
*
|
|
833
|
+
* Lowering pattern (slice 7a — f64 only):
|
|
834
|
+
* local.get $__gen_buffer
|
|
835
|
+
* <emit value>
|
|
836
|
+
* call $__gen_push_f64
|
|
837
|
+
*/
|
|
838
|
+
export interface IrInstrGenPush extends IrInstrBase {
|
|
839
|
+
readonly kind: "gen.push";
|
|
840
|
+
readonly value: IrValueId;
|
|
841
|
+
}
|
|
842
|
+
/**
|
|
843
|
+
* Slice 6 part 3 (#1182) — opaque iterator handle for the host iterator
|
|
844
|
+
* protocol. Calls `__iterator(iterable)` to obtain the iterator object.
|
|
845
|
+
*
|
|
846
|
+
* Lowering:
|
|
847
|
+
* <emit iterable> ;; pushes externref
|
|
848
|
+
* call $__iterator ;; -> externref (the iterator)
|
|
849
|
+
*
|
|
850
|
+
* Result type: `irVal({ kind: "externref" })`.
|
|
851
|
+
*/
|
|
852
|
+
export interface IrInstrIterNew extends IrInstrBase {
|
|
853
|
+
readonly kind: "iter.new";
|
|
854
|
+
readonly iterable: IrValueId;
|
|
855
|
+
/** True if this is a `for await` loop — calls `__async_iterator` instead. False for slice 6. */
|
|
856
|
+
readonly async: boolean;
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Call iter.next() and return the result object handle (externref).
|
|
860
|
+
* The result is later split into `done` / `value` via separate instrs
|
|
861
|
+
* so the optimizer can decide whether to evaluate `value` (skip if done).
|
|
862
|
+
*
|
|
863
|
+
* Lowering: <emit iter>; call $__iterator_next -> externref
|
|
864
|
+
*
|
|
865
|
+
* Result type: `irVal({ kind: "externref" })`. Side-effecting (advances
|
|
866
|
+
* the iterator) — DCE must not eliminate it.
|
|
867
|
+
*/
|
|
868
|
+
export interface IrInstrIterNext extends IrInstrBase {
|
|
869
|
+
readonly kind: "iter.next";
|
|
870
|
+
readonly iter: IrValueId;
|
|
871
|
+
}
|
|
872
|
+
/**
|
|
873
|
+
* Test whether an iterator-result object's `.done` is true.
|
|
874
|
+
*
|
|
875
|
+
* Lowering: <emit resultObj>; call $__iterator_done -> i32
|
|
876
|
+
*
|
|
877
|
+
* Result type: `irVal({ kind: "i32" })`. The operand field is named
|
|
878
|
+
* `resultObj` (not `result`) to avoid colliding with the SSA-def
|
|
879
|
+
* `result` field inherited from `IrInstrBase`.
|
|
880
|
+
*/
|
|
881
|
+
export interface IrInstrIterDone extends IrInstrBase {
|
|
882
|
+
readonly kind: "iter.done";
|
|
883
|
+
readonly resultObj: IrValueId;
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Read the `.value` slot of an iterator-result object.
|
|
887
|
+
*
|
|
888
|
+
* Lowering: <emit resultObj>; call $__iterator_value -> externref
|
|
889
|
+
*
|
|
890
|
+
* Result type: `irVal({ kind: "externref" })`. See `IrInstrIterDone`
|
|
891
|
+
* for the `resultObj` naming rationale.
|
|
892
|
+
*/
|
|
893
|
+
export interface IrInstrIterValue extends IrInstrBase {
|
|
894
|
+
readonly kind: "iter.value";
|
|
895
|
+
readonly resultObj: IrValueId;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Call `iter.return()` if defined. Used by the iterator-close try/finally
|
|
899
|
+
* so abrupt exits notify the iterator (slice 6 step E, deferred to a
|
|
900
|
+
* try/finally-aware follow-up).
|
|
901
|
+
*
|
|
902
|
+
* Lowering: <emit iter>; call $__iterator_return
|
|
903
|
+
*
|
|
904
|
+
* Result type: void (`result: null`). Side-effecting.
|
|
905
|
+
*/
|
|
906
|
+
export interface IrInstrIterReturn extends IrInstrBase {
|
|
907
|
+
readonly kind: "iter.return";
|
|
908
|
+
readonly iter: IrValueId;
|
|
909
|
+
}
|
|
910
|
+
/**
|
|
911
|
+
* Statement-level `for (const <bind> of <iterable>) <body>` loop using
|
|
912
|
+
* the host iterator protocol. The lowerer emits:
|
|
913
|
+
*
|
|
914
|
+
* <emit iterable>
|
|
915
|
+
* call $__iterator
|
|
916
|
+
* local.set <iterSlot>
|
|
917
|
+
* block
|
|
918
|
+
* loop
|
|
919
|
+
* local.get <iterSlot>
|
|
920
|
+
* call $__iterator_next
|
|
921
|
+
* local.tee <resultSlot>
|
|
922
|
+
* call $__iterator_done
|
|
923
|
+
* br_if 1 ;; exit loop on done=true
|
|
924
|
+
* local.get <resultSlot>
|
|
925
|
+
* call $__iterator_value
|
|
926
|
+
* local.set <elementSlot>
|
|
927
|
+
* <body instrs>
|
|
928
|
+
* br 0 ;; continue
|
|
929
|
+
* end
|
|
930
|
+
* end
|
|
931
|
+
* local.get <iterSlot>
|
|
932
|
+
* call $__iterator_return ;; normal-exit close
|
|
933
|
+
*
|
|
934
|
+
* The iterable must be an IR value of externref type (the from-ast
|
|
935
|
+
* layer inserts a `coerce.to_externref` if the source value isn't
|
|
936
|
+
* already externref). Slot indices are pre-allocated via
|
|
937
|
+
* `IrFunctionBuilder.declareSlot`.
|
|
938
|
+
*
|
|
939
|
+
* Result: void (`result: null`).
|
|
940
|
+
*/
|
|
941
|
+
export interface IrInstrForOfIter extends IrInstrBase {
|
|
942
|
+
readonly kind: "forof.iter";
|
|
943
|
+
/** SSA value of the iterable as externref (caller pre-coerces). */
|
|
944
|
+
readonly iterable: IrValueId;
|
|
945
|
+
/** Pre-allocated externref slot for the iterator handle. */
|
|
946
|
+
readonly iterSlot: number;
|
|
947
|
+
/** Pre-allocated externref slot for the iterator-result object. */
|
|
948
|
+
readonly resultSlot: number;
|
|
949
|
+
/** Pre-allocated externref slot for the current element value. */
|
|
950
|
+
readonly elementSlot: number;
|
|
951
|
+
/** Body instrs emitted inside the loop. */
|
|
952
|
+
readonly body: readonly IrInstr[];
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Slice 7a (#1169f) — generator function epilogue. Pushes the buffer + the
|
|
956
|
+
* pending-throw cell (always `ref.null.extern` in slice 7a) and calls
|
|
957
|
+
* `__create_generator(buffer, pendingThrow)` to produce the Generator-like
|
|
958
|
+
* object the function returns.
|
|
959
|
+
*
|
|
960
|
+
* Lowering pattern (slice 7a — synchronous-throw subset):
|
|
961
|
+
* local.get $__gen_buffer
|
|
962
|
+
* ref.null.extern ;; pendingThrow always null in 7a
|
|
963
|
+
* call $__create_generator
|
|
964
|
+
* ;; result: externref Generator object — left on stack for the
|
|
965
|
+
* ;; surrounding `return` terminator.
|
|
966
|
+
*
|
|
967
|
+
* Slice 7a does NOT yet emit the try/catch wrapping that legacy uses for
|
|
968
|
+
* deferred-throw semantics (#928). Throws inside the body propagate
|
|
969
|
+
* immediately (matches V8 generators on the FIRST `.next()` call but
|
|
970
|
+
* differs from spec on subsequent calls). A future slice (7-throw) will
|
|
971
|
+
* add the wrapping by carrying the preceding body instrs in this instr,
|
|
972
|
+
* similar to `forof.vec.body`.
|
|
973
|
+
*
|
|
974
|
+
* Result type: `irVal({ kind: "externref" })` — the Generator object.
|
|
975
|
+
* The function's terminator should be `return [result]`.
|
|
976
|
+
*/
|
|
977
|
+
export interface IrInstrGenEpilogue extends IrInstrBase {
|
|
978
|
+
readonly kind: "gen.epilogue";
|
|
979
|
+
}
|
|
980
|
+
/**
|
|
981
|
+
* Slice 7b (#1169f) — `yield* <iterable>` delegation. Drains the inner
|
|
982
|
+
* iterable into the outer generator's `__gen_buffer` by calling the
|
|
983
|
+
* `__gen_yield_star(buf, iterable)` host import (signature
|
|
984
|
+
* `(externref, externref) → void`; the host iterates the inner via
|
|
985
|
+
* `Symbol.iterator` and pushes each value).
|
|
986
|
+
*
|
|
987
|
+
* The `inner` operand MUST already be coerced to externref by the
|
|
988
|
+
* caller (`lowerYield` in `from-ast.ts` inserts a `coerce.to_externref`
|
|
989
|
+
* upstream). The lowerer just emits the buffer-load, value, and call.
|
|
990
|
+
*
|
|
991
|
+
* Result is void. Only valid inside `funcKind === "generator"`. The
|
|
992
|
+
* lowerer reads `IrFunction.generatorBufferSlot` for the buffer
|
|
993
|
+
* `local.get`.
|
|
994
|
+
*
|
|
995
|
+
* Lowering pattern:
|
|
996
|
+
* local.get $__gen_buffer
|
|
997
|
+
* <emit inner> ;; already externref
|
|
998
|
+
* call $__gen_yield_star
|
|
999
|
+
*
|
|
1000
|
+
* Spec divergence note: ECMA-262 §27.5.3.7 says `yield*` evaluates to
|
|
1001
|
+
* the inner iterator's `return` value (the `IteratorResult.value` when
|
|
1002
|
+
* `done` becomes true). Under the eager-buffer model this is discarded;
|
|
1003
|
+
* `yield*` evaluates to `undefined`. Matches the legacy compiler's
|
|
1004
|
+
* behaviour (`misc.ts:177-202`).
|
|
1005
|
+
*/
|
|
1006
|
+
export interface IrInstrGenYieldStar extends IrInstrBase {
|
|
1007
|
+
readonly kind: "gen.yieldStar";
|
|
1008
|
+
readonly inner: IrValueId;
|
|
1009
|
+
}
|
|
1010
|
+
/**
|
|
1011
|
+
* Slice 10 (#1169i) — `new ExternClass(arg1, arg2, ...)` where
|
|
1012
|
+
* `ExternClass` is a host-provided builtin (RegExp, Uint8Array, …). The
|
|
1013
|
+
* Wasm-level result is opaque externref; downstream code accesses it
|
|
1014
|
+
* via `extern.call` / `extern.prop`.
|
|
1015
|
+
*
|
|
1016
|
+
* Lowering:
|
|
1017
|
+
* <emit each arg>
|
|
1018
|
+
* call $<className>_new
|
|
1019
|
+
*
|
|
1020
|
+
* Result type: `{ kind: "extern", className }`.
|
|
1021
|
+
*/
|
|
1022
|
+
export interface IrInstrExternNew extends IrInstrBase {
|
|
1023
|
+
readonly kind: "extern.new";
|
|
1024
|
+
readonly className: string;
|
|
1025
|
+
readonly args: readonly IrValueId[];
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* Slice 10 (#1169i) — method call on an extern-class value. `receiver`
|
|
1029
|
+
* is the externref handle; `method` names a method registered on the
|
|
1030
|
+
* class via `ctx.externClasses`.
|
|
1031
|
+
*
|
|
1032
|
+
* Lowering:
|
|
1033
|
+
* <emit receiver>
|
|
1034
|
+
* <emit each arg>
|
|
1035
|
+
* call $<className>_<method>
|
|
1036
|
+
*
|
|
1037
|
+
* Result type: matches the registered method's first result. Void
|
|
1038
|
+
* methods carry `result: null` and `resultType: null`.
|
|
1039
|
+
*/
|
|
1040
|
+
export interface IrInstrExternCall extends IrInstrBase {
|
|
1041
|
+
readonly kind: "extern.call";
|
|
1042
|
+
readonly className: string;
|
|
1043
|
+
readonly method: string;
|
|
1044
|
+
readonly receiver: IrValueId;
|
|
1045
|
+
readonly args: readonly IrValueId[];
|
|
1046
|
+
}
|
|
1047
|
+
/**
|
|
1048
|
+
* Slice 10 (#1169i) — property read on an extern-class value.
|
|
1049
|
+
*
|
|
1050
|
+
* Lowering:
|
|
1051
|
+
* <emit receiver>
|
|
1052
|
+
* call $<className>_get_<property>
|
|
1053
|
+
*
|
|
1054
|
+
* Result type: the property's registered ValType, wrapped as `IrType.val`.
|
|
1055
|
+
*/
|
|
1056
|
+
export interface IrInstrExternProp extends IrInstrBase {
|
|
1057
|
+
readonly kind: "extern.prop";
|
|
1058
|
+
readonly className: string;
|
|
1059
|
+
readonly property: string;
|
|
1060
|
+
readonly receiver: IrValueId;
|
|
1061
|
+
}
|
|
1062
|
+
/**
|
|
1063
|
+
* Slice 10 (#1169i) — property write on an extern-class value (for
|
|
1064
|
+
* non-readonly props).
|
|
1065
|
+
*
|
|
1066
|
+
* Lowering:
|
|
1067
|
+
* <emit receiver>
|
|
1068
|
+
* <emit value>
|
|
1069
|
+
* call $<className>_set_<property>
|
|
1070
|
+
*/
|
|
1071
|
+
export interface IrInstrExternPropSet extends IrInstrBase {
|
|
1072
|
+
readonly kind: "extern.propSet";
|
|
1073
|
+
readonly className: string;
|
|
1074
|
+
readonly property: string;
|
|
1075
|
+
readonly receiver: IrValueId;
|
|
1076
|
+
readonly value: IrValueId;
|
|
1077
|
+
}
|
|
1078
|
+
/**
|
|
1079
|
+
* Slice 10 (#1169i) — RegExp literal `/pattern/flags`. Lowers to
|
|
1080
|
+
* `RegExp_new(pattern, flags)`. The pattern + flags are registered as
|
|
1081
|
+
* string-literal globals (the legacy `collectStringLiterals` pass
|
|
1082
|
+
* already collects RegExp pattern/flags as string literals — see
|
|
1083
|
+
* `src/codegen/index.ts:3274-3278` — so by the time the IR emits this
|
|
1084
|
+
* instr the corresponding string globals exist).
|
|
1085
|
+
*
|
|
1086
|
+
* Result type: `{ kind: "extern", className: "RegExp" }`.
|
|
1087
|
+
*/
|
|
1088
|
+
export interface IrInstrRegExpLiteral extends IrInstrBase {
|
|
1089
|
+
readonly kind: "extern.regex";
|
|
1090
|
+
readonly pattern: string;
|
|
1091
|
+
readonly flags: string;
|
|
1092
|
+
}
|
|
1093
|
+
/**
|
|
1094
|
+
* Statement-level `for (const c of <string>) <body>` loop using the
|
|
1095
|
+
* native-strings counter pattern. Emitted only when the resolver
|
|
1096
|
+
* reports `nativeStrings(): true` — host-strings mode falls through
|
|
1097
|
+
* to `forof.iter` upstream in `lowerForOfStatement`.
|
|
1098
|
+
*
|
|
1099
|
+
* The lowerer emits:
|
|
1100
|
+
* <emit str>
|
|
1101
|
+
* local.set <strSlot>
|
|
1102
|
+
* local.get <strSlot>
|
|
1103
|
+
* struct.get $AnyString $len
|
|
1104
|
+
* local.set <lengthSlot>
|
|
1105
|
+
* i32.const 0
|
|
1106
|
+
* local.set <counterSlot>
|
|
1107
|
+
* block
|
|
1108
|
+
* loop
|
|
1109
|
+
* local.get <counterSlot>
|
|
1110
|
+
* local.get <lengthSlot>
|
|
1111
|
+
* i32.ge_s
|
|
1112
|
+
* br_if 1
|
|
1113
|
+
* local.get <strSlot>
|
|
1114
|
+
* local.get <counterSlot>
|
|
1115
|
+
* call $__str_charAt
|
|
1116
|
+
* local.set <elementSlot>
|
|
1117
|
+
* <body instrs>
|
|
1118
|
+
* local.get <counterSlot>
|
|
1119
|
+
* i32.const 1
|
|
1120
|
+
* i32.add
|
|
1121
|
+
* local.set <counterSlot>
|
|
1122
|
+
* br 0
|
|
1123
|
+
* end
|
|
1124
|
+
* end
|
|
1125
|
+
*
|
|
1126
|
+
* Slot types (set by from-ast):
|
|
1127
|
+
* counterSlot — i32
|
|
1128
|
+
* lengthSlot — i32
|
|
1129
|
+
* strSlot — `(ref $AnyString)` (resolver.resolveString())
|
|
1130
|
+
* elementSlot — `(ref $AnyString)` — each iteration produces a
|
|
1131
|
+
* single-char string
|
|
1132
|
+
*
|
|
1133
|
+
* Result: void (`result: null`).
|
|
1134
|
+
*/
|
|
1135
|
+
export interface IrInstrForOfString extends IrInstrBase {
|
|
1136
|
+
readonly kind: "forof.string";
|
|
1137
|
+
/** SSA value of the string (IrType.string). */
|
|
1138
|
+
readonly str: IrValueId;
|
|
1139
|
+
readonly counterSlot: number;
|
|
1140
|
+
readonly lengthSlot: number;
|
|
1141
|
+
readonly strSlot: number;
|
|
1142
|
+
readonly elementSlot: number;
|
|
1143
|
+
/** Body instrs emitted inside the loop. */
|
|
1144
|
+
readonly body: readonly IrInstr[];
|
|
1145
|
+
}
|
|
1146
|
+
/**
|
|
1147
|
+
* Slice 9 (#1169h) — throw an exception. The `value` is coerced to externref
|
|
1148
|
+
* upstream (the `__exn` tag's signature is `(externref)`). After throw,
|
|
1149
|
+
* control transfers to the nearest enclosing catch matching the tag, or
|
|
1150
|
+
* unwinds out of the function.
|
|
1151
|
+
*
|
|
1152
|
+
* The instr produces NO SSA value (control doesn't fall through), so
|
|
1153
|
+
* `result` and `resultType` are always null. The verifier treats it as a
|
|
1154
|
+
* "stop" instr — instructions after it in the same block are unreachable
|
|
1155
|
+
* in source but still validated structurally.
|
|
1156
|
+
*
|
|
1157
|
+
* Lowering:
|
|
1158
|
+
* <emit value> ;; pushes externref
|
|
1159
|
+
* throw $__exn
|
|
1160
|
+
*/
|
|
1161
|
+
export interface IrInstrThrow extends IrInstrBase {
|
|
1162
|
+
readonly kind: "throw";
|
|
1163
|
+
readonly value: IrValueId;
|
|
1164
|
+
}
|
|
1165
|
+
/**
|
|
1166
|
+
* Slice 12 (#1280) — `while (cond) body` loop.
|
|
1167
|
+
*
|
|
1168
|
+
* Lowering pattern:
|
|
1169
|
+
* block
|
|
1170
|
+
* loop
|
|
1171
|
+
* <cond instrs> ;; computes condValue
|
|
1172
|
+
* <emit condValue> ;; pushes the i32 boolean
|
|
1173
|
+
* i32.eqz
|
|
1174
|
+
* br_if 1 ;; exit on falsy
|
|
1175
|
+
* <body instrs>
|
|
1176
|
+
* br 0 ;; continue
|
|
1177
|
+
* end
|
|
1178
|
+
* end
|
|
1179
|
+
*
|
|
1180
|
+
* `condValue` MUST be the SSA result of an instruction in `cond` (or
|
|
1181
|
+
* an outer-scope value that's loaded into `cond`'s last instr). The
|
|
1182
|
+
* resolver coerces non-i32 values to i32 via the standard truthy
|
|
1183
|
+
* lowering path — for now the from-ast layer enforces an i32 result.
|
|
1184
|
+
*
|
|
1185
|
+
* Result: void (`result: null`).
|
|
1186
|
+
*/
|
|
1187
|
+
export interface IrInstrWhileLoop extends IrInstrBase {
|
|
1188
|
+
readonly kind: "while.loop";
|
|
1189
|
+
/** Instructions that compute the condition. Re-evaluated per iteration. */
|
|
1190
|
+
readonly cond: readonly IrInstr[];
|
|
1191
|
+
/** SSA value of the condition (an i32 boolean). */
|
|
1192
|
+
readonly condValue: IrValueId;
|
|
1193
|
+
/** Body instructions executed each iteration when the cond is truthy. */
|
|
1194
|
+
readonly body: readonly IrInstr[];
|
|
1195
|
+
}
|
|
1196
|
+
/**
|
|
1197
|
+
* Slice 12 (#1280) — `for (init; cond; update) body` loop.
|
|
1198
|
+
*
|
|
1199
|
+
* The init clause is emitted by the from-ast layer as ordinary IR
|
|
1200
|
+
* statements BEFORE the `for.loop` instr (init is just a let-decl or
|
|
1201
|
+
* an assignment expression statement, no special encoding needed).
|
|
1202
|
+
* The instr carries cond, body, update.
|
|
1203
|
+
*
|
|
1204
|
+
* Lowering pattern:
|
|
1205
|
+
* block
|
|
1206
|
+
* loop
|
|
1207
|
+
* <cond instrs>
|
|
1208
|
+
* <emit condValue>
|
|
1209
|
+
* i32.eqz
|
|
1210
|
+
* br_if 1
|
|
1211
|
+
* <body instrs>
|
|
1212
|
+
* <update instrs> ;; runs after body, before re-evaluating cond
|
|
1213
|
+
* br 0
|
|
1214
|
+
* end
|
|
1215
|
+
* end
|
|
1216
|
+
*
|
|
1217
|
+
* Result: void (`result: null`).
|
|
1218
|
+
*/
|
|
1219
|
+
export interface IrInstrForLoop extends IrInstrBase {
|
|
1220
|
+
readonly kind: "for.loop";
|
|
1221
|
+
/** Instructions that compute the condition. Re-evaluated per iteration. */
|
|
1222
|
+
readonly cond: readonly IrInstr[];
|
|
1223
|
+
/** SSA value of the condition (an i32 boolean). */
|
|
1224
|
+
readonly condValue: IrValueId;
|
|
1225
|
+
/** Body instructions executed each iteration when the cond is truthy. */
|
|
1226
|
+
readonly body: readonly IrInstr[];
|
|
1227
|
+
/** Update instructions executed after the body each iteration. */
|
|
1228
|
+
readonly update: readonly IrInstr[];
|
|
1229
|
+
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Slice 9 (#1169h) — try / catch / finally as a declarative statement-level
|
|
1232
|
+
* instr. Mirrors the slice-6 `forof.vec` shape: the body / catch handler /
|
|
1233
|
+
* finally are self-contained Instr[] buffers, and the lowerer emits the
|
|
1234
|
+
* structured Wasm `try`/`catch`/`catch_all` op directly without
|
|
1235
|
+
* restructuring the IR's block graph.
|
|
1236
|
+
*
|
|
1237
|
+
* Encoding:
|
|
1238
|
+
* - `body` the try block's instructions.
|
|
1239
|
+
* - `catchClause` optional. When present, encodes a source-level
|
|
1240
|
+
* `catch (e) { ... }` (or `catch { ... }`).
|
|
1241
|
+
* * `payloadSlot` — slot of `(externref)` that
|
|
1242
|
+
* receives the thrown value at handler entry
|
|
1243
|
+
* (or -1 when there is no source binding).
|
|
1244
|
+
* * `body` — handler instructions.
|
|
1245
|
+
* - `finallyBody` optional. When present, the lowerer inlines this
|
|
1246
|
+
* buffer at every "abrupt completion" path:
|
|
1247
|
+
* * normal exit of try body
|
|
1248
|
+
* * normal exit of catch body
|
|
1249
|
+
* * a synthesized catch_all that re-throws
|
|
1250
|
+
*
|
|
1251
|
+
* Acceptable shapes (selector-enforced):
|
|
1252
|
+
* try { ... } catch (e) { ... } catchClause set
|
|
1253
|
+
* try { ... } catch { ... } catchClause set, payloadSlot=-1
|
|
1254
|
+
* try { ... } finally { ... } finallyBody set
|
|
1255
|
+
* try { ... } catch (e) { ... } finally { ... } both set
|
|
1256
|
+
*
|
|
1257
|
+
* Result is void (`result: null`).
|
|
1258
|
+
*/
|
|
1259
|
+
export interface IrInstrTry extends IrInstrBase {
|
|
1260
|
+
readonly kind: "try";
|
|
1261
|
+
/** Try block instructions. */
|
|
1262
|
+
readonly body: readonly IrInstr[];
|
|
1263
|
+
/** Optional source-level catch handler. */
|
|
1264
|
+
readonly catchClause?: {
|
|
1265
|
+
/**
|
|
1266
|
+
* Externref-typed slot index that the lowerer writes the caught
|
|
1267
|
+
* exception into at handler entry. `-1` when the source has no
|
|
1268
|
+
* binding (`catch { ... }`).
|
|
1269
|
+
*/
|
|
1270
|
+
readonly payloadSlot: number;
|
|
1271
|
+
readonly body: readonly IrInstr[];
|
|
1272
|
+
};
|
|
1273
|
+
/** Optional finally body, inlined at every exit path. */
|
|
1274
|
+
readonly finallyBody?: readonly IrInstr[];
|
|
1275
|
+
}
|
|
1276
|
+
export type IrInstr = IrInstrConst | IrInstrCall | IrInstrGlobalGet | IrInstrGlobalSet | IrInstrBinary | IrInstrUnary | IrInstrSelect | IrInstrIf | IrInstrRawWasm | IrInstrBox | IrInstrUnbox | IrInstrTagTest | IrInstrStringConst | IrInstrStringConcat | IrInstrStringEq | IrInstrStringLen | IrInstrObjectNew | IrInstrObjectGet | IrInstrObjectSet | IrInstrClosureNew | IrInstrClosureCap | IrInstrClosureCall | IrInstrRefCellNew | IrInstrRefCellGet | IrInstrRefCellSet | IrInstrClassNew | IrInstrClassGet | IrInstrClassSet | IrInstrClassCall | IrInstrSlotRead | IrInstrSlotWrite | IrInstrVecLen | IrInstrVecGet | IrInstrVecNewFixed | IrInstrForOfVec | IrInstrCoerceToExternref | IrInstrIterNew | IrInstrIterNext | IrInstrIterDone | IrInstrIterValue | IrInstrIterReturn | IrInstrForOfIter | IrInstrGenPush | IrInstrGenEpilogue | IrInstrGenYieldStar | IrInstrForOfString | IrInstrThrow | IrInstrTry | IrInstrExternNew | IrInstrExternCall | IrInstrExternProp | IrInstrExternPropSet | IrInstrRegExpLiteral | IrInstrWhileLoop | IrInstrForLoop | IrInstrAwait | IrInstrAsyncReturn | IrInstrAsyncThrow;
|
|
1277
|
+
/**
|
|
1278
|
+
* Slice 6 (#1169e) — declaration of one Wasm-local slot used for cross-
|
|
1279
|
+
* iteration mutable state. Slots are allocated by the IR builder and
|
|
1280
|
+
* surface in the lowered Wasm function as additional locals appended
|
|
1281
|
+
* after the params and the SSA-driven locals.
|
|
1282
|
+
*
|
|
1283
|
+
* - `index` stable slot index, used by `slot.read` / `slot.write`.
|
|
1284
|
+
* NOT a Wasm local index — the lowerer translates slot
|
|
1285
|
+
* index N to Wasm local index `params + ssaLocals + N`.
|
|
1286
|
+
* - `name` debug name for the local.
|
|
1287
|
+
* - `type` primitive ValType (i32 / f64 / etc.) — slots only
|
|
1288
|
+
* carry primitives; reference-typed cross-iteration
|
|
1289
|
+
* state is rare in slice-6 loop bodies.
|
|
1290
|
+
*/
|
|
1291
|
+
export interface IrSlotDef {
|
|
1292
|
+
readonly index: number;
|
|
1293
|
+
readonly name: string;
|
|
1294
|
+
readonly type: ValType;
|
|
1295
|
+
}
|
|
1296
|
+
export interface IrBranch {
|
|
1297
|
+
readonly target: IrBlockId;
|
|
1298
|
+
readonly args: readonly IrValueId[];
|
|
1299
|
+
}
|
|
1300
|
+
export type IrBlockId = number & {
|
|
1301
|
+
readonly __brand: "IrBlockId";
|
|
1302
|
+
};
|
|
1303
|
+
export declare function asBlockId(n: number): IrBlockId;
|
|
1304
|
+
export interface IrTerminatorReturn {
|
|
1305
|
+
readonly kind: "return";
|
|
1306
|
+
readonly values: readonly IrValueId[];
|
|
1307
|
+
readonly site?: IrSiteId;
|
|
1308
|
+
}
|
|
1309
|
+
export interface IrTerminatorBr {
|
|
1310
|
+
readonly kind: "br";
|
|
1311
|
+
readonly branch: IrBranch;
|
|
1312
|
+
readonly site?: IrSiteId;
|
|
1313
|
+
}
|
|
1314
|
+
export interface IrTerminatorBrIf {
|
|
1315
|
+
readonly kind: "br_if";
|
|
1316
|
+
readonly condition: IrValueId;
|
|
1317
|
+
readonly ifTrue: IrBranch;
|
|
1318
|
+
readonly ifFalse: IrBranch;
|
|
1319
|
+
readonly site?: IrSiteId;
|
|
1320
|
+
}
|
|
1321
|
+
export interface IrTerminatorUnreachable {
|
|
1322
|
+
readonly kind: "unreachable";
|
|
1323
|
+
readonly site?: IrSiteId;
|
|
1324
|
+
}
|
|
1325
|
+
export type IrTerminator = IrTerminatorReturn | IrTerminatorBr | IrTerminatorBrIf | IrTerminatorUnreachable;
|
|
1326
|
+
export interface IrBlock {
|
|
1327
|
+
readonly id: IrBlockId;
|
|
1328
|
+
/** SSA values bound on entry (replace phi nodes). Types are parallel to `blockArgTypes`. */
|
|
1329
|
+
readonly blockArgs: readonly IrValueId[];
|
|
1330
|
+
readonly blockArgTypes: readonly IrType[];
|
|
1331
|
+
readonly instrs: readonly IrInstr[];
|
|
1332
|
+
readonly terminator: IrTerminator;
|
|
1333
|
+
}
|
|
1334
|
+
export interface IrParam {
|
|
1335
|
+
readonly value: IrValueId;
|
|
1336
|
+
readonly type: IrType;
|
|
1337
|
+
readonly name: string;
|
|
1338
|
+
}
|
|
1339
|
+
export interface IrFunction {
|
|
1340
|
+
readonly name: string;
|
|
1341
|
+
readonly params: readonly IrParam[];
|
|
1342
|
+
readonly resultTypes: readonly IrType[];
|
|
1343
|
+
/** Entry block is always `blocks[0]`. */
|
|
1344
|
+
readonly blocks: readonly IrBlock[];
|
|
1345
|
+
readonly exported: boolean;
|
|
1346
|
+
/** Highest IrValueId allocated + 1 (useful for re-entering the builder). */
|
|
1347
|
+
readonly valueCount: number;
|
|
1348
|
+
/**
|
|
1349
|
+
* Slice 3 (#1169c): for closure-lifted bodies only, identifies the
|
|
1350
|
+
* subtype struct that captures live on. Set by `liftClosureBody` in
|
|
1351
|
+
* `from-ast.ts`. The lowerer reads this when emitting `closure.cap`
|
|
1352
|
+
* to compute the correct ref.cast target. Absent for nested function
|
|
1353
|
+
* declarations (which don't take a __self param) and for outer
|
|
1354
|
+
* functions.
|
|
1355
|
+
*/
|
|
1356
|
+
readonly closureSubtype?: {
|
|
1357
|
+
readonly signature: IrClosureSignature;
|
|
1358
|
+
readonly captureFieldTypes: readonly IrType[];
|
|
1359
|
+
};
|
|
1360
|
+
/**
|
|
1361
|
+
* Slice 6 (#1169e): Wasm-local slots used for cross-iteration mutable
|
|
1362
|
+
* state in for-of loops. Empty for functions that don't contain a
|
|
1363
|
+
* for-of (or any other slot user). Slot indices are stable; the
|
|
1364
|
+
* lowerer maps slot index N to Wasm local index
|
|
1365
|
+
* `params.length + ssaLocalCount + N`
|
|
1366
|
+
* — i.e. slots come AFTER the SSA-driven locals.
|
|
1367
|
+
*/
|
|
1368
|
+
readonly slots?: readonly IrSlotDef[];
|
|
1369
|
+
/**
|
|
1370
|
+
* Slice 7a (#1169f) — distinguishes regular / generator / async
|
|
1371
|
+
* functions. Set by `lowerFunctionAstToIr` from the AST node's
|
|
1372
|
+
* `asteriskToken` and `async` modifier. The lowerer reads this to:
|
|
1373
|
+
* - `"generator"`: select the externref Wasm-result type regardless
|
|
1374
|
+
* of the source-level annotation (the function returns a
|
|
1375
|
+
* Generator-like object, not the source-declared yield element
|
|
1376
|
+
* type), AND register the function name in `ctx.generatorFunctions`
|
|
1377
|
+
* downstream (for any name-based dispatch the legacy already wires).
|
|
1378
|
+
* - `"async"`: register in `ctx.asyncFunctions` so the export glue's
|
|
1379
|
+
* `wrapAsyncReturn` wraps the result in `Promise.resolve`. (Slice
|
|
1380
|
+
* 7d, not 7a.)
|
|
1381
|
+
* - `"regular"`: no special treatment (default if absent).
|
|
1382
|
+
*/
|
|
1383
|
+
readonly funcKind?: "regular" | "generator" | "async";
|
|
1384
|
+
/**
|
|
1385
|
+
* Slice 7a (#1169f) — for `funcKind === "generator"` functions only,
|
|
1386
|
+
* the slot index (in `slots`) of the `__gen_buffer` Wasm-local. The
|
|
1387
|
+
* lowerer reads this when emitting `gen.push` / `gen.epilogue` to
|
|
1388
|
+
* produce the `local.get $__gen_buffer` op.
|
|
1389
|
+
*/
|
|
1390
|
+
readonly generatorBufferSlot?: number;
|
|
1391
|
+
}
|
|
1392
|
+
export interface IrModule {
|
|
1393
|
+
readonly functions: readonly IrFunction[];
|
|
1394
|
+
}
|
|
1395
|
+
export declare function isIrFuncRef(x: unknown): x is IrFuncRef;
|
|
1396
|
+
export declare function isIrGlobalRef(x: unknown): x is IrGlobalRef;
|
|
1397
|
+
export declare function isIrTypeRef(x: unknown): x is IrTypeRef;
|
|
1398
|
+
/**
|
|
1399
|
+
* Invoke `fn` once per nested `IrInstr[]` buffer carried directly by `instr`
|
|
1400
|
+
* (NOT recursively — see `forEachInstrDeep` for the deep walk). The exhaustive
|
|
1401
|
+
* switch is the authoritative list of buffer-bearing kinds; the trailing
|
|
1402
|
+
* `never` assignment makes a missing case a compile error, so a new
|
|
1403
|
+
* buffer-bearing instr kind cannot be added without extending this one place.
|
|
1404
|
+
*
|
|
1405
|
+
* Buffer order is the lowering/evaluation order (cond before body before
|
|
1406
|
+
* update; then before else; body/catch/finally) so callers that care about
|
|
1407
|
+
* order (def registration) get it for free.
|
|
1408
|
+
*/
|
|
1409
|
+
export declare function forEachNestedBuffer(instr: IrInstr, fn: (buffer: readonly IrInstr[]) => void): void;
|
|
1410
|
+
/**
|
|
1411
|
+
* Visit `instr` and every instruction nested within its buffers, recursively
|
|
1412
|
+
* (pre-order: the containing instr before its buffer contents). The single
|
|
1413
|
+
* deep-walk primitive shared by the verifier (def registration) and the
|
|
1414
|
+
* alloc-discipline pass (allocation retirement).
|
|
1415
|
+
*/
|
|
1416
|
+
export declare function forEachInstrDeep(instr: IrInstr, visit: (i: IrInstr) => void): void;
|
|
1417
|
+
/**
|
|
1418
|
+
* Rebuild `instr` with each nested buffer replaced by `mapBuffer(buffer)` — the
|
|
1419
|
+
* write-side companion to `forEachNestedBuffer`, used by the hygiene passes
|
|
1420
|
+
* (#1925) to fold / DCE *inside* control-flow buffers. Buffers are passed in the
|
|
1421
|
+
* same evaluation order `forEachNestedBuffer` yields them.
|
|
1422
|
+
*
|
|
1423
|
+
* Reference-equality preserving: when `mapBuffer` returns each buffer unchanged
|
|
1424
|
+
* (same array reference), the original `instr` is returned as-is, so callers can
|
|
1425
|
+
* detect "no change" by `===` and keep their fixpoint contract. A non-buffer
|
|
1426
|
+
* instr is always returned unchanged.
|
|
1427
|
+
*/
|
|
1428
|
+
export declare function mapNestedBuffers(instr: IrInstr, mapBuffer: (buffer: readonly IrInstr[]) => readonly IrInstr[]): IrInstr;
|
|
1429
|
+
/**
|
|
1430
|
+
* The direct SSA-value operands of `instr` — the values it reads at its own
|
|
1431
|
+
* level, NOT including operands buried in nested buffers. This is the canonical
|
|
1432
|
+
* single-count mapping used by the verifier and DCE (so e.g. `closure.call`'s
|
|
1433
|
+
* callee is counted once; the lowering use-counter's intentional double-count
|
|
1434
|
+
* for Wasm-local materialisation stays local to lower.ts).
|
|
1435
|
+
*
|
|
1436
|
+
* For buffer-bearing control-flow instrs, the operands surfaced here are only
|
|
1437
|
+
* the ones evaluated at the instr's own level: `if` → cond; `while/for` →
|
|
1438
|
+
* condValue; `forof.*` → the iterable/vec/str; `try` → none. Buffer-interior
|
|
1439
|
+
* uses are reached via `collectUses(instr, { deep: true })`.
|
|
1440
|
+
*/
|
|
1441
|
+
export declare function directUses(instr: IrInstr): readonly IrValueId[];
|
|
1442
|
+
/**
|
|
1443
|
+
* Collect the SSA-value uses of `instr`. Shallow by default (== `directUses`);
|
|
1444
|
+
* with `{ deep: true }` it also walks every nested buffer via
|
|
1445
|
+
* `forEachNestedBuffer`, surfacing buffer-interior uses too. The deep form is
|
|
1446
|
+
* what DCE needs so values referenced only inside a loop/if/for-of/try buffer
|
|
1447
|
+
* survive liveness — the exact bug (#1922) the per-kind ad-hoc walkers caused
|
|
1448
|
+
* for `while.loop`/`for.loop`.
|
|
1449
|
+
*/
|
|
1450
|
+
export declare function collectUses(instr: IrInstr, opts?: {
|
|
1451
|
+
readonly deep?: boolean;
|
|
1452
|
+
}): readonly IrValueId[];
|