@scriptc/compiler 0.0.21 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ambient/scriptc-node-fallback.d.ts +78 -34
- package/dist/backend/cc-cache.test.d.ts +1 -0
- package/dist/backend/cc-cache.test.js +2507 -0
- package/dist/backend/cc-cache.test.js.map +1 -0
- package/dist/backend/cc.d.ts +69 -11
- package/dist/backend/cc.js +1937 -222
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emit-exprs.js +355 -8
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-walkers.js +108 -7
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +16 -0
- package/dist/backend/emission/emitter.js +23 -2
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +1 -0
- package/dist/backend/llvm/dyn.js +305 -8
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +527 -2
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/compat/fetch-profile.d.ts +108 -0
- package/dist/compat/fetch-profile.js +482 -0
- package/dist/compat/fetch-profile.js.map +1 -0
- package/dist/coverage/surface-manifest.js +54 -0
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +21 -8
- package/dist/frontend/lowering/lower-builtins.js +137 -14
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.js +40 -0
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.js +4 -3
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +2 -2
- package/dist/frontend/lowering/lower-exprs.js +63 -12
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-island.d.ts +102 -7
- package/dist/frontend/lowering/lower-island.js +1702 -26
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.js +17 -1
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.js +25 -5
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +39 -0
- package/dist/frontend/lowering/lowerer.js +286 -18
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.js +12 -0
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/program.d.ts +16 -0
- package/dist/frontend/program.js +130 -6
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/types.d.ts +14 -7
- package/dist/frontend/types.js +95 -31
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +70 -14
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +32 -16
- package/dist/ir/nodes.js +36 -28
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +61 -1
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/int-infer.js +7 -1
- package/dist/library/int-infer.js.map +1 -1
- package/dist/library/int-infer.test.js +80 -0
- package/dist/library/int-infer.test.js.map +1 -1
- package/dist/library/sidecar-validate.js +5 -0
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +3 -0
- package/dist/library/sidecar.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +859 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { canMarshalFuncIntoIsland, CAUGHT, DYN, F64, islandCallbackRet, islandPromisePayloadTag, isRefCounted, isUnitType, MAY_THROW_LIB_FNS, moduleUsesDynInvoke, moduleUsesFetch, moduleUsesFsWatch, moduleUsesHttpServer, moduleUsesNet, moduleUsesProcessEvents, moduleUsesStream, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, STRING, typeEquals, typeKey, VOID } from "../../ir/nodes.js";
|
|
1
|
+
import { canMarshalFuncIntoIsland, CAUGHT, DYN, F64, islandCallbackRet, islandPromisePayloadTag, isRefCounted, isUnitType, MAY_THROW_LIB_FNS, moduleUsesDynInvoke, moduleUsesFetch, moduleUsesFsWatch, moduleUsesHttpServer, moduleUsesNet, moduleUsesProcessEvents, moduleUsesStream, moduleUsesTls, moduleUsesTlsCa, RUNTIME_EMITTER_CLASS, RUNTIME_ERROR_CLASSES, RUNTIME_STREAM_CLASSES, STRING, typeEquals, typeKey, VOID } from "../../ir/nodes.js";
|
|
2
2
|
import { computeMayThrow } from "../emission/may-throw.js";
|
|
3
3
|
import { mangleArgPack, mangleAsyncSpawn, mangleClassNew, mangleClassObj, mangleClassRetain, mangleFnClosure, mangleFunction, mangleGenDrop, mangleGenResThunk, mangleGenSpawn, mangleGlobal, mangleLocal, mangleRecordNew, mangleRecordStruct, mangleResolveThunk, mangleTrampoline, mangleVtStruct, mangleWrapper } from "../mangle.js";
|
|
4
4
|
import { BlockBuilder } from "./blocks.js";
|
|
@@ -351,6 +351,16 @@ const LIB_FN_SYMS = {
|
|
|
351
351
|
// defineProps throw Node's TypeErrors (all in the may-throw seed set —
|
|
352
352
|
// the generic path emits the standard pending check). typeof and the
|
|
353
353
|
// ambient-this read never throw. The fs dyn read is the sync-fs story.
|
|
354
|
+
"fetch.start": "scr_fetch_static",
|
|
355
|
+
"fetch.responseJson": "scr_fetch_response_json",
|
|
356
|
+
"fetch.responseText": "scr_fetch_response_text",
|
|
357
|
+
"fetch.responseBytes": "scr_fetch_response_bytes",
|
|
358
|
+
"fetch.abortTimeout": "scr_fetch_abort_timeout",
|
|
359
|
+
"fetch.abortNow": "scr_fetch_abort_now",
|
|
360
|
+
"fetch.abortAny": "scr_fetch_abort_any",
|
|
361
|
+
"fetch.streamNew": "scr_fetch_stream_new",
|
|
362
|
+
"fetch.streamFrom": "scr_fetch_stream_from",
|
|
363
|
+
"fetch.readerRead": "scr_fetch_reader_read",
|
|
354
364
|
"json.parse": "scr_json_parse",
|
|
355
365
|
"dyn.keySet": "scr_dyn_key_set",
|
|
356
366
|
"dyn.iterPack": "scr_dyn_iter_pack",
|
|
@@ -626,6 +636,8 @@ const STREAM_CANONICAL_CBS = {
|
|
|
626
636
|
* the stream/emitter slice of emit-exprs.ts's markings, applied before
|
|
627
637
|
* dispatch so generic and special shapes share one table. */
|
|
628
638
|
const USES_TIMERS_LIB_FNS = new Set([
|
|
639
|
+
"fetch.start",
|
|
640
|
+
"fetch.abortTimeout", "fetch.streamNew", "fetch.streamFrom",
|
|
629
641
|
"readable.new", "writable.new", "duplex.new", "transform.new", "passthrough.new",
|
|
630
642
|
"readable.init", "writable.init", "duplex.init", "transform.init", "passthrough.init",
|
|
631
643
|
"readable.newDyn", "writable.newDyn", "duplex.newDyn", "transform.newDyn", "passthrough.newDyn",
|
|
@@ -770,6 +782,15 @@ class LlEmitter {
|
|
|
770
782
|
* typeKey → thunk symbol (CEmitter.resolveThunks). */
|
|
771
783
|
resolveThunks = new Map();
|
|
772
784
|
resolveThunkDefs = [];
|
|
785
|
+
/** ReadableStream.from adapters keep typed arrays by reference and box
|
|
786
|
+
* one current element per pull. */
|
|
787
|
+
streamFromArrayAdapters = new Map();
|
|
788
|
+
/** Identity-preserving static→dyn capsules used by Web APIs whose values
|
|
789
|
+
* remain directly observable (stream chunks and AbortSignal reasons). */
|
|
790
|
+
liveDynRefAdapters = new Map();
|
|
791
|
+
/** Runtime-arm dispatchers for live union values. */
|
|
792
|
+
liveDynUnionRefAdapters = new Map();
|
|
793
|
+
dynPromiseAdapters = new Map();
|
|
773
794
|
unionsById = new Map();
|
|
774
795
|
recordsById = new Map();
|
|
775
796
|
tracedShapes;
|
|
@@ -1038,6 +1059,7 @@ class LlEmitter {
|
|
|
1038
1059
|
// any island entry (the engine's lazy boot consults it) — cc.ts
|
|
1039
1060
|
// compiles scr_fetch.c on the same predicate.
|
|
1040
1061
|
const usesFetch = moduleUsesFetch(this.mod);
|
|
1062
|
+
const snapshotsTlsCa = moduleUsesTls(this.mod) || moduleUsesTlsCa(this.mod);
|
|
1041
1063
|
const hasRefGlobals = globals.some((g) => isRefCounted(g.type)) || fnValueProps.length > 0;
|
|
1042
1064
|
// Declared NOW — the extern block flushes before main assembles.
|
|
1043
1065
|
if (usesEvents)
|
|
@@ -1054,6 +1076,9 @@ class LlEmitter {
|
|
|
1054
1076
|
this.declare(`declare void @scr_http_dyn_install()`);
|
|
1055
1077
|
if (usesFetch)
|
|
1056
1078
|
this.declare(`declare void @scr_fetch_install()`);
|
|
1079
|
+
if (snapshotsTlsCa) {
|
|
1080
|
+
this.declare(`declare void @scr_tls_ca_install()`);
|
|
1081
|
+
}
|
|
1057
1082
|
if (usesEvents && hasRefGlobals) {
|
|
1058
1083
|
this.declare(`declare void @scr_run_exit_listeners(double)`);
|
|
1059
1084
|
this.declare(`declare i32 @scr_exit_code_hint_get()`);
|
|
@@ -1298,7 +1323,7 @@ class LlEmitter {
|
|
|
1298
1323
|
...(usesEvents ? [` call void @scr_events_install()`] : []),
|
|
1299
1324
|
// fs.watch programs fill the loop's watch hooks the same way —
|
|
1300
1325
|
// scr_watch.c links only when this line is emitted.
|
|
1301
|
-
...(usesFsWatch ? [` call void @scr_watch_install()`] : []), ...(usesFetch ? [` call void @scr_fetch_install()`] : []), ...(usesNet ? [` call void @scr_net_install()`, ` call void @scr_net_dyn_install()`] : []), ...(usesHttp ? [` call void @scr_http_dyn_install()`] : []), ...(usesStream ? [` call void @scr_stream_install()`] : []), ` call void @scr_lib_init(i32 %argc, ptr %argv)`, ...(asyncEntry
|
|
1326
|
+
...(usesFsWatch ? [` call void @scr_watch_install()`] : []), ...(snapshotsTlsCa ? [` call void @scr_tls_ca_install()`] : []), ...(usesFetch ? [` call void @scr_fetch_install()`] : []), ...(usesNet ? [` call void @scr_net_install()`, ` call void @scr_net_dyn_install()`] : []), ...(usesHttp ? [` call void @scr_http_dyn_install()`] : []), ...(usesStream ? [` call void @scr_stream_install()`] : []), ` call void @scr_lib_init(i32 %argc, ptr %argv)`, ...(asyncEntry
|
|
1302
1327
|
? [` %top = call ptr @${mangleAsyncSpawn(this.mod.entry)}()`]
|
|
1303
1328
|
: [` call void @${mangleFunction(this.mod.entry)}()`]),
|
|
1304
1329
|
// Uncaught exception from top-level code: Node exits 1.
|
|
@@ -5821,6 +5846,29 @@ class LlEmitter {
|
|
|
5821
5846
|
return this.own({ name: t, type: e.type });
|
|
5822
5847
|
}
|
|
5823
5848
|
const v = this.emitExpr(e.value);
|
|
5849
|
+
if (e.liveRef) {
|
|
5850
|
+
if (v.type.kind === "union") {
|
|
5851
|
+
const adapter = this.liveDynUnionRefAdapter(v.type);
|
|
5852
|
+
const boxed = B.tmp();
|
|
5853
|
+
B.line(`${boxed} = call ptr @${adapter}(ptr ${v.name})`);
|
|
5854
|
+
return this.own({ name: boxed, type: e.type });
|
|
5855
|
+
}
|
|
5856
|
+
if (!this.streamTypedRefEligible(v.type)) {
|
|
5857
|
+
throw new Error(`llvm emitter bug: live dyn ref of ${typeKey(v.type)}`);
|
|
5858
|
+
}
|
|
5859
|
+
const key = typeKey(v.type);
|
|
5860
|
+
let adapter = this.liveDynRefAdapters.get(key);
|
|
5861
|
+
if (!adapter) {
|
|
5862
|
+
const prefix = `sc_ldr_${this.liveDynRefAdapters.size}`;
|
|
5863
|
+
adapter = this.streamTypedRefMaterializeAdapter(v.type, { prefix, adapters: new Map() }, `${prefix}_materialize`);
|
|
5864
|
+
this.liveDynRefAdapters.set(key, adapter);
|
|
5865
|
+
}
|
|
5866
|
+
const rc = vAdapters(this, v.type);
|
|
5867
|
+
this.declare(`declare ptr @scr_dyn_new_typed_ref(ptr, ptr, ptr, ptr, i64, ptr, ptr)`);
|
|
5868
|
+
const boxed = B.tmp();
|
|
5869
|
+
B.line(`${boxed} = call ptr @scr_dyn_new_typed_ref(ptr ${v.name}, ptr ${rc.retain}, ptr ${rc.release}, ptr ${this.cstr(key)}, i64 ${Buffer.byteLength(key, "utf8")}, ptr @${adapter.snapshot}, ptr ${adapter.commit})`);
|
|
5870
|
+
return this.own({ name: boxed, type: e.type });
|
|
5871
|
+
}
|
|
5824
5872
|
if (v.type.kind === "func") {
|
|
5825
5873
|
// A closure boxes as the checked-dynamic tree's function kind: retained closure +
|
|
5826
5874
|
// the per-signature call thunk + the interned signature key. The
|
|
@@ -6560,6 +6608,15 @@ class LlEmitter {
|
|
|
6560
6608
|
return t;
|
|
6561
6609
|
});
|
|
6562
6610
|
}
|
|
6611
|
+
case "callFnThis": {
|
|
6612
|
+
const pack = argPack(args.slice(2).map((x) => x.name));
|
|
6613
|
+
this.declare(`declare ptr @scr_jsval_call_this(ptr, ptr, i32, ptr)`);
|
|
6614
|
+
return fallible(() => {
|
|
6615
|
+
const t = B.tmp();
|
|
6616
|
+
B.line(`${t} = call ptr @scr_jsval_call_this(ptr ${a(0)}, ptr ${a(1)}, i32 ${args.length - 2}, ptr ${pack})`);
|
|
6617
|
+
return t;
|
|
6618
|
+
});
|
|
6619
|
+
}
|
|
6563
6620
|
case "callSpread": {
|
|
6564
6621
|
// Spread application (`f(...pre, ...s)`): the prelude helper's
|
|
6565
6622
|
// real spread syntax — iterator protocols are the engine's own,
|
|
@@ -9119,6 +9176,410 @@ class LlEmitter {
|
|
|
9119
9176
|
B.line(`call void @sc_bad_key()`);
|
|
9120
9177
|
B.terminate(`unreachable`);
|
|
9121
9178
|
}
|
|
9179
|
+
dynPromiseAdapter(inner) {
|
|
9180
|
+
if (!isRefCounted(inner) || inner.kind === "dyn") {
|
|
9181
|
+
throw new Error(`dynamic promise adapter requires a concrete reference type, got ${typeKey(inner)}`);
|
|
9182
|
+
}
|
|
9183
|
+
const key = typeKey(inner);
|
|
9184
|
+
const existing = this.dynPromiseAdapters.get(key);
|
|
9185
|
+
if (existing)
|
|
9186
|
+
return existing;
|
|
9187
|
+
const sym = `sc_dpa_${this.dynPromiseAdapters.size}`;
|
|
9188
|
+
this.dynPromiseAdapters.set(key, sym);
|
|
9189
|
+
this.declare(`declare ptr @scr_promise_payload_ref(ptr)`);
|
|
9190
|
+
this.declare(`declare void @scr_dyn_release_v(ptr)`);
|
|
9191
|
+
this.declare(`declare zeroext i1 @scr_exc_pending()`);
|
|
9192
|
+
this.declare(`declare void @scr_promise_reject_pending(ptr)`);
|
|
9193
|
+
const B = new BlockBuilder();
|
|
9194
|
+
const dyn = B.tmp();
|
|
9195
|
+
const value = B.tmp();
|
|
9196
|
+
const pending = B.tmp();
|
|
9197
|
+
B.line(`${dyn} = call ptr @scr_promise_payload_ref(ptr %src)`);
|
|
9198
|
+
B.line(`${value} = call ptr @${this.dyn.dynCheckHelper(inner)}(ptr ${dyn}, ptr null)`);
|
|
9199
|
+
B.line(`call void @scr_dyn_release_v(ptr ${dyn})`);
|
|
9200
|
+
B.line(`${pending} = call zeroext i1 @scr_exc_pending()`);
|
|
9201
|
+
const fail = B.newLabel("sra.fail");
|
|
9202
|
+
const ok = B.newLabel("sra.ok");
|
|
9203
|
+
B.condBr(pending, fail, ok);
|
|
9204
|
+
B.startBlock(fail);
|
|
9205
|
+
B.line(`call void @scr_promise_reject_pending(ptr %dst)`);
|
|
9206
|
+
B.terminate(`ret void`);
|
|
9207
|
+
B.startBlock(ok);
|
|
9208
|
+
if (inner.kind === "string") {
|
|
9209
|
+
this.declare(`declare void @scr_promise_fulfill_str(ptr, ptr)`);
|
|
9210
|
+
B.line(`call void @scr_promise_fulfill_str(ptr %dst, ptr ${value})`);
|
|
9211
|
+
}
|
|
9212
|
+
else {
|
|
9213
|
+
const rc = vAdapters(this, inner);
|
|
9214
|
+
this.declare(`declare void @scr_promise_fulfill_ref(ptr, ptr, ptr, ptr, ptr)`);
|
|
9215
|
+
B.line(`call void @scr_promise_fulfill_ref(ptr %dst, ptr ${value}, ptr ${rc.retain}, ptr ${rc.release}, ptr ${traceArg(this, inner)})`);
|
|
9216
|
+
}
|
|
9217
|
+
B.terminate(`ret void`);
|
|
9218
|
+
this.resolveThunkDefs.push(`define internal void @${sym}(ptr %dst, ptr %src) ${FN_ATTRS} { ; checked-dynamic promise exit ${key}`, B.render(), `}`, ``);
|
|
9219
|
+
return sym;
|
|
9220
|
+
}
|
|
9221
|
+
streamTypedRefCommitAdapter(t, snapshot) {
|
|
9222
|
+
if (t.kind === "bytes") {
|
|
9223
|
+
const commit = `${snapshot}_commit`;
|
|
9224
|
+
const check = this.dyn.dynCheckHelper(t);
|
|
9225
|
+
this.declare(`declare void @scr_bytes_copy_contents(ptr, ptr)`);
|
|
9226
|
+
this.declare(`declare void @scr_bytes_release(ptr)`);
|
|
9227
|
+
this.resolveThunkDefs.push(`define internal void @${commit}(ptr %target, ptr %d) ${FN_ATTRS} { ; commit live stream element ${typeKey(t)}`, `entry:`, ` %next = call ptr @${check}(ptr %d, ptr null)`, ` %missing = icmp eq ptr %next, null`, ` br i1 %missing, label %done, label %copy`, `copy:`, ` call void @scr_bytes_copy_contents(ptr %target, ptr %next)`, ` call void @scr_bytes_release(ptr %next)`, ` br label %done`, `done:`, ` ret void`, `}`, ``);
|
|
9228
|
+
return `@${commit}`;
|
|
9229
|
+
}
|
|
9230
|
+
if (t.kind === "array") {
|
|
9231
|
+
const commit = `${snapshot}_commit`;
|
|
9232
|
+
const check = this.dyn.dynCheckHelper(t);
|
|
9233
|
+
this.declare(`declare void @scr_arr_release(ptr)`);
|
|
9234
|
+
this.resolveThunkDefs.push(`define internal void @${commit}(ptr %target, ptr %d) ${FN_ATTRS} { ; commit live stream element ${typeKey(t)}`, `entry:`, ` %next = call ptr @${check}(ptr %d, ptr null)`, ` %missing = icmp eq ptr %next, null`, ` br i1 %missing, label %done, label %swap`, `swap:`, ` %target_len_ptr = getelementptr inbounds %ScrArr, ptr %target, i64 0, i32 1`, ` %next_len_ptr = getelementptr inbounds %ScrArr, ptr %next, i64 0, i32 1`, ` %target_len = load i64, ptr %target_len_ptr`, ` %next_len = load i64, ptr %next_len_ptr`, ` store i64 %next_len, ptr %target_len_ptr`, ` store i64 %target_len, ptr %next_len_ptr`, ` %target_cap_ptr = getelementptr inbounds %ScrArr, ptr %target, i64 0, i32 2`, ` %next_cap_ptr = getelementptr inbounds %ScrArr, ptr %next, i64 0, i32 2`, ` %target_cap = load i64, ptr %target_cap_ptr`, ` %next_cap = load i64, ptr %next_cap_ptr`, ` store i64 %next_cap, ptr %target_cap_ptr`, ` store i64 %target_cap, ptr %next_cap_ptr`, ` %target_data_ptr = getelementptr inbounds %ScrArr, ptr %target, i64 0, i32 7`, ` %next_data_ptr = getelementptr inbounds %ScrArr, ptr %next, i64 0, i32 7`, ` %target_data = load ptr, ptr %target_data_ptr`, ` %next_data = load ptr, ptr %next_data_ptr`, ` store ptr %next_data, ptr %target_data_ptr`, ` store ptr %target_data, ptr %next_data_ptr`, ` call void @scr_arr_release(ptr %next)`, ` br label %done`, `done:`, ` ret void`, `}`, ``);
|
|
9235
|
+
return `@${commit}`;
|
|
9236
|
+
}
|
|
9237
|
+
if (t.kind !== "record")
|
|
9238
|
+
return "null";
|
|
9239
|
+
const shape = this.recordsById.get(t.shapeId);
|
|
9240
|
+
if (!shape) {
|
|
9241
|
+
throw new Error(`llvm emitter bug: stream typed-ref commit of unknown shape ${t.shapeId}`);
|
|
9242
|
+
}
|
|
9243
|
+
const commit = `${snapshot}_commit`;
|
|
9244
|
+
const check = this.dyn.dynCheckHelper(t);
|
|
9245
|
+
const lines = [
|
|
9246
|
+
`define internal void @${commit}(ptr %target, ptr %d) ${FN_ATTRS} { ; commit live stream element ${typeKey(t)}`,
|
|
9247
|
+
`entry:`,
|
|
9248
|
+
` %next = call ptr @${check}(ptr %d, ptr null)`,
|
|
9249
|
+
` %missing = icmp eq ptr %next, null`,
|
|
9250
|
+
` br i1 %missing, label %done, label %swap`,
|
|
9251
|
+
`swap:`,
|
|
9252
|
+
];
|
|
9253
|
+
const members = [
|
|
9254
|
+
...shape.fields.map((field, index) => ({
|
|
9255
|
+
index: index + 1,
|
|
9256
|
+
type: llFieldType(field.type),
|
|
9257
|
+
name: field.name,
|
|
9258
|
+
})),
|
|
9259
|
+
...(shape.indexValue
|
|
9260
|
+
? [{
|
|
9261
|
+
index: shape.fields.length + 1,
|
|
9262
|
+
type: "ptr",
|
|
9263
|
+
name: "[key: string] overflow",
|
|
9264
|
+
}]
|
|
9265
|
+
: []),
|
|
9266
|
+
];
|
|
9267
|
+
members.forEach((member, index) => {
|
|
9268
|
+
lines.push(` %tp${index} = getelementptr inbounds %${mangleRecordStruct(t.shapeId)}, ptr %target, i64 0, i32 ${member.index}`, ` %np${index} = getelementptr inbounds %${mangleRecordStruct(t.shapeId)}, ptr %next, i64 0, i32 ${member.index}`, ` %old${index} = load ${member.type}, ptr %tp${index} ; ${member.name}`, ` %new${index} = load ${member.type}, ptr %np${index}`, ` store ${member.type} %new${index}, ptr %tp${index}`, ` store ${member.type} %old${index}, ptr %np${index}`);
|
|
9269
|
+
});
|
|
9270
|
+
lines.push(` call void ${releaseSym(this, t)}(ptr %next)`, ` br label %done`, `done:`, ` ret void`, `}`, ``);
|
|
9271
|
+
this.resolveThunkDefs.push(...lines);
|
|
9272
|
+
return `@${commit}`;
|
|
9273
|
+
}
|
|
9274
|
+
/** Box the mutable payload of a union directly, preserving the identity
|
|
9275
|
+
* that AbortSignal reasons and stream chunks expose. Scalar/unit arms use
|
|
9276
|
+
* the ordinary union-to-dyn converter. */
|
|
9277
|
+
liveDynUnionRefAdapter(t) {
|
|
9278
|
+
const key = typeKey(t);
|
|
9279
|
+
const existing = this.liveDynUnionRefAdapters.get(key);
|
|
9280
|
+
if (existing)
|
|
9281
|
+
return existing;
|
|
9282
|
+
const union = this.unionsById.get(t.unionId);
|
|
9283
|
+
if (!union) {
|
|
9284
|
+
throw new Error(`llvm emitter bug: live dyn ref of unknown union ${t.unionId}`);
|
|
9285
|
+
}
|
|
9286
|
+
const mutableArms = union.arms
|
|
9287
|
+
.map((arm, tag) => ({ arm, tag }))
|
|
9288
|
+
.filter(({ arm }) => this.streamTypedRefEligible(arm));
|
|
9289
|
+
if (mutableArms.length === 0) {
|
|
9290
|
+
throw new Error(`llvm emitter bug: live dyn ref of immutable union ${key}`);
|
|
9291
|
+
}
|
|
9292
|
+
const sym = `sc_ldu_${this.liveDynUnionRefAdapters.size}`;
|
|
9293
|
+
this.liveDynUnionRefAdapters.set(key, sym);
|
|
9294
|
+
this.declare(`declare ptr @scr_dyn_new_typed_ref(ptr, ptr, ptr, ptr, i64, ptr, ptr)`);
|
|
9295
|
+
const adapters = new Map();
|
|
9296
|
+
for (const { arm, tag } of mutableArms) {
|
|
9297
|
+
const prefix = `${sym}_${tag}`;
|
|
9298
|
+
adapters.set(tag, this.streamTypedRefMaterializeAdapter(arm, { prefix, adapters: new Map() }, `${prefix}_materialize`));
|
|
9299
|
+
}
|
|
9300
|
+
const B = new BlockBuilder();
|
|
9301
|
+
const tagPtr = B.tmp();
|
|
9302
|
+
const tagValue = B.tmp();
|
|
9303
|
+
B.line(`${tagPtr} = getelementptr inbounds %ScrUnion, ptr %u, i64 0, i32 1`);
|
|
9304
|
+
B.line(`${tagValue} = load i32, ptr ${tagPtr}`);
|
|
9305
|
+
const fallback = B.newLabel("ldu.dyn");
|
|
9306
|
+
const armLabels = mutableArms.map(() => B.newLabel("ldu.ref"));
|
|
9307
|
+
B.terminate(`switch i32 ${tagValue}, label %${fallback} [ ${mutableArms.map(({ tag }, index) => `i32 ${tag}, label %${armLabels[index]}`).join(" ")} ]`);
|
|
9308
|
+
mutableArms.forEach(({ arm, tag }, index) => {
|
|
9309
|
+
const adapter = adapters.get(tag);
|
|
9310
|
+
const rc = vAdapters(this, arm);
|
|
9311
|
+
const armKey = typeKey(arm);
|
|
9312
|
+
B.startBlock(armLabels[index]);
|
|
9313
|
+
const payloadPtr = B.tmp();
|
|
9314
|
+
const payload = B.tmp();
|
|
9315
|
+
const boxed = B.tmp();
|
|
9316
|
+
B.line(`${payloadPtr} = getelementptr inbounds %ScrUnion, ptr %u, i64 0, i32 5`);
|
|
9317
|
+
B.line(`${payload} = load ptr, ptr ${payloadPtr}`);
|
|
9318
|
+
B.line(`${boxed} = call ptr @scr_dyn_new_typed_ref(ptr ${payload}, ptr ${rc.retain}, ptr ${rc.release}, ptr ${this.cstr(armKey)}, i64 ${Buffer.byteLength(armKey, "utf8")}, ptr @${adapter.snapshot}, ptr ${adapter.commit})`);
|
|
9319
|
+
B.terminate(`ret ptr ${boxed}`);
|
|
9320
|
+
});
|
|
9321
|
+
B.startBlock(fallback);
|
|
9322
|
+
const boxed = B.tmp();
|
|
9323
|
+
B.line(`${boxed} = call ptr @${this.dyn.toDynHelper(t)}(ptr %u)`);
|
|
9324
|
+
B.terminate(`ret ptr ${boxed}`);
|
|
9325
|
+
this.resolveThunkDefs.push(`define internal ptr @${sym}(ptr %u) ${FN_ATTRS} { ; materialize live union value ${key}`, B.render(), `}`, ``);
|
|
9326
|
+
return sym;
|
|
9327
|
+
}
|
|
9328
|
+
streamTypedRefEligible(t) {
|
|
9329
|
+
return t.kind === "record" || t.kind === "array" || t.kind === "bytes";
|
|
9330
|
+
}
|
|
9331
|
+
streamTypedRefBoxValue(B, t, value, ctx) {
|
|
9332
|
+
const boxed = B.tmp();
|
|
9333
|
+
if (!this.streamTypedRefEligible(t)) {
|
|
9334
|
+
const valueTy = t.kind === "f64"
|
|
9335
|
+
? "double"
|
|
9336
|
+
: t.kind === "bool"
|
|
9337
|
+
? "i1"
|
|
9338
|
+
: "ptr";
|
|
9339
|
+
B.line(`${boxed} = call ptr @${this.dyn.toDynHelper(t)}(${valueTy} ${value})`);
|
|
9340
|
+
return boxed;
|
|
9341
|
+
}
|
|
9342
|
+
const nested = this.streamTypedRefMaterializeAdapter(t, ctx);
|
|
9343
|
+
const rc = vAdapters(this, t);
|
|
9344
|
+
const key = typeKey(t);
|
|
9345
|
+
this.declare(`declare ptr @scr_dyn_new_typed_ref(ptr, ptr, ptr, ptr, i64, ptr, ptr)`);
|
|
9346
|
+
B.line(`${boxed} = call ptr @scr_dyn_new_typed_ref(ptr ${value}, ptr ${rc.retain}, ptr ${rc.release}, ptr ${this.cstr(key)}, i64 ${Buffer.byteLength(key, "utf8")}, ptr @${nested.snapshot}, ptr ${nested.commit})`);
|
|
9347
|
+
return boxed;
|
|
9348
|
+
}
|
|
9349
|
+
/** LLVM twin of the C stream materializer: mutable reference children
|
|
9350
|
+
* are their own typed capsules, so writes through a nested alias commit
|
|
9351
|
+
* to the nested static source immediately. */
|
|
9352
|
+
streamTypedRefMaterializeAdapter(t, ctx, preferredSnapshot) {
|
|
9353
|
+
const key = typeKey(t);
|
|
9354
|
+
const existing = ctx.adapters.get(key);
|
|
9355
|
+
if (existing)
|
|
9356
|
+
return existing;
|
|
9357
|
+
const snapshot = preferredSnapshot ??
|
|
9358
|
+
`${ctx.prefix}_nested_${ctx.adapters.size}`;
|
|
9359
|
+
const adapter = { snapshot, commit: "null" };
|
|
9360
|
+
ctx.adapters.set(key, adapter);
|
|
9361
|
+
adapter.commit = this.streamTypedRefCommitAdapter(t, snapshot);
|
|
9362
|
+
const B = new BlockBuilder();
|
|
9363
|
+
if (t.kind === "record") {
|
|
9364
|
+
const shape = this.recordsById.get(t.shapeId);
|
|
9365
|
+
if (!shape) {
|
|
9366
|
+
throw new Error(`llvm emitter bug: stream typed-ref materialize of unknown shape ${t.shapeId}`);
|
|
9367
|
+
}
|
|
9368
|
+
/* Keep the ordinary converter for index-signature/listener records;
|
|
9369
|
+
* their source-identity and overflow walks have extra contracts.
|
|
9370
|
+
* Declared-field records and tuples cover the live stream values. */
|
|
9371
|
+
const ordinary = shape.indexValue || shape.fields.some((field) => field.name === "handleEvent" && field.type.kind === "func");
|
|
9372
|
+
if (ordinary) {
|
|
9373
|
+
const out = B.tmp();
|
|
9374
|
+
B.line(`${out} = call ptr @${this.dyn.toDynHelper(t)}(ptr %p)`);
|
|
9375
|
+
B.terminate(`ret ptr ${out}`);
|
|
9376
|
+
}
|
|
9377
|
+
else if (shape.tuple) {
|
|
9378
|
+
this.declare(`declare ptr @scr_dyn_new_arr()`);
|
|
9379
|
+
this.declare(`declare void @scr_dyn_arr_push(ptr, ptr)`);
|
|
9380
|
+
const out = B.tmp();
|
|
9381
|
+
B.line(`${out} = call ptr @scr_dyn_new_arr()`);
|
|
9382
|
+
const fields = [...shape.fields].sort((a, b) => Number(a.name) - Number(b.name));
|
|
9383
|
+
for (const field of fields) {
|
|
9384
|
+
const index = shape.fields.indexOf(field) + 1;
|
|
9385
|
+
const fieldPtr = B.tmp();
|
|
9386
|
+
const fieldValue = B.tmp();
|
|
9387
|
+
B.line(`${fieldPtr} = getelementptr inbounds %${mangleRecordStruct(t.shapeId)}, ptr %p, i64 0, i32 ${index}`);
|
|
9388
|
+
B.line(`${fieldValue} = load ${llFieldType(field.type)}, ptr ${fieldPtr}`);
|
|
9389
|
+
const boxed = this.streamTypedRefBoxValue(B, field.type, fieldValue, ctx);
|
|
9390
|
+
B.line(`call void @scr_dyn_arr_push(ptr ${out}, ptr ${boxed})`);
|
|
9391
|
+
}
|
|
9392
|
+
B.terminate(`ret ptr ${out}`);
|
|
9393
|
+
}
|
|
9394
|
+
else {
|
|
9395
|
+
this.declare(`declare ptr @scr_dyn_new_obj()`);
|
|
9396
|
+
this.declare(`declare void @scr_dyn_obj_set(ptr, ptr, i64, ptr)`);
|
|
9397
|
+
const out = B.tmp();
|
|
9398
|
+
B.line(`${out} = call ptr @scr_dyn_new_obj()`);
|
|
9399
|
+
const byName = new Map(shape.fields.map((field) => [field.name, field]));
|
|
9400
|
+
const order = shape.declaredOrder ?? shape.fields.map((field) => field.name);
|
|
9401
|
+
const inOrder = new Set(order);
|
|
9402
|
+
const fields = [
|
|
9403
|
+
...order.map((name) => byName.get(name)).filter((field) => field !== undefined),
|
|
9404
|
+
...shape.fields.filter((field) => !inOrder.has(field.name)),
|
|
9405
|
+
];
|
|
9406
|
+
for (const field of fields) {
|
|
9407
|
+
const index = shape.fields.indexOf(field) + 1;
|
|
9408
|
+
const fieldPtr = B.tmp();
|
|
9409
|
+
const fieldValue = B.tmp();
|
|
9410
|
+
B.line(`${fieldPtr} = getelementptr inbounds %${mangleRecordStruct(t.shapeId)}, ptr %p, i64 0, i32 ${index}`);
|
|
9411
|
+
B.line(`${fieldValue} = load ${llFieldType(field.type)}, ptr ${fieldPtr}`);
|
|
9412
|
+
const boxed = this.streamTypedRefBoxValue(B, field.type, fieldValue, ctx);
|
|
9413
|
+
B.line(`call void @scr_dyn_obj_set(ptr ${out}, ptr ${this.cstr(field.name)}, i64 ${Buffer.byteLength(field.name, "utf8")}, ptr ${boxed})`);
|
|
9414
|
+
}
|
|
9415
|
+
B.terminate(`ret ptr ${out}`);
|
|
9416
|
+
}
|
|
9417
|
+
}
|
|
9418
|
+
else if (t.kind === "array") {
|
|
9419
|
+
const elem = t.elem;
|
|
9420
|
+
this.declare(`declare ptr @scr_dyn_new_arr()`);
|
|
9421
|
+
this.declare(`declare void @scr_dyn_arr_push(ptr, ptr)`);
|
|
9422
|
+
this.declare(`declare double @scr_arr_len(ptr)`);
|
|
9423
|
+
const out = B.tmp();
|
|
9424
|
+
B.line(`${out} = call ptr @scr_dyn_new_arr()`);
|
|
9425
|
+
const len = B.tmp();
|
|
9426
|
+
B.line(`${len} = call double @scr_arr_len(ptr %p)`);
|
|
9427
|
+
const iSlot = B.slot();
|
|
9428
|
+
B.entryAllocas.push(`${iSlot} = alloca double`);
|
|
9429
|
+
B.line(`store double ${f64Lit(0)}, ptr ${iSlot}`);
|
|
9430
|
+
const condition = B.newLabel("strm.c");
|
|
9431
|
+
const body = B.newLabel("strm.b");
|
|
9432
|
+
const done = B.newLabel("strm.e");
|
|
9433
|
+
B.br(condition);
|
|
9434
|
+
B.startBlock(condition);
|
|
9435
|
+
const index = B.tmp();
|
|
9436
|
+
const more = B.tmp();
|
|
9437
|
+
B.line(`${index} = load double, ptr ${iSlot}`);
|
|
9438
|
+
B.line(`${more} = fcmp olt double ${index}, ${len}`);
|
|
9439
|
+
B.condBr(more, body, done);
|
|
9440
|
+
B.startBlock(body);
|
|
9441
|
+
let value;
|
|
9442
|
+
if (elem.kind === "f64" || elem.kind === "bool") {
|
|
9443
|
+
const valueTy = elem.kind === "f64" ? "double" : "i1";
|
|
9444
|
+
this.declare(`declare ${elem.kind === "bool" ? "zeroext i1" : valueTy} @scr_arr_get_${elem.kind}(ptr, double)`);
|
|
9445
|
+
value = B.tmp();
|
|
9446
|
+
B.line(`${value} = call ${valueTy} @scr_arr_get_${elem.kind}(ptr %p, double ${index})`);
|
|
9447
|
+
}
|
|
9448
|
+
else {
|
|
9449
|
+
this.declare(`declare ptr @scr_arr_get_ref(ptr, double)`);
|
|
9450
|
+
value = B.tmp();
|
|
9451
|
+
B.line(`${value} = call ptr @scr_arr_get_ref(ptr %p, double ${index}) ; +1`);
|
|
9452
|
+
}
|
|
9453
|
+
const boxed = this.streamTypedRefBoxValue(B, elem, value, ctx);
|
|
9454
|
+
B.line(`call void @scr_dyn_arr_push(ptr ${out}, ptr ${boxed})`);
|
|
9455
|
+
if (isRefCounted(elem)) {
|
|
9456
|
+
B.line(`call void ${releaseSym(this, elem)}(ptr ${value})`);
|
|
9457
|
+
}
|
|
9458
|
+
const next = B.tmp();
|
|
9459
|
+
B.line(`${next} = fadd double ${index}, ${f64Lit(1)}`);
|
|
9460
|
+
B.line(`store double ${next}, ptr ${iSlot}`);
|
|
9461
|
+
B.br(condition);
|
|
9462
|
+
B.startBlock(done);
|
|
9463
|
+
B.terminate(`ret ptr ${out}`);
|
|
9464
|
+
}
|
|
9465
|
+
else {
|
|
9466
|
+
const out = B.tmp();
|
|
9467
|
+
B.line(`${out} = call ptr @${this.dyn.toDynHelper(t)}(ptr %p)`);
|
|
9468
|
+
B.terminate(`ret ptr ${out}`);
|
|
9469
|
+
}
|
|
9470
|
+
this.resolveThunkDefs.push(`define internal ptr @${snapshot}(ptr %p) ${FN_ATTRS} { ; materialize live stream value ${key}`, B.render(), `}`, ``);
|
|
9471
|
+
return adapter;
|
|
9472
|
+
}
|
|
9473
|
+
streamFromArrayAdapter(t) {
|
|
9474
|
+
const elem = t.elem;
|
|
9475
|
+
const key = typeKey(elem);
|
|
9476
|
+
const existing = this.streamFromArrayAdapters.get(key);
|
|
9477
|
+
if (existing)
|
|
9478
|
+
return existing;
|
|
9479
|
+
const sym = `sc_sfa_${this.streamFromArrayAdapters.size}`;
|
|
9480
|
+
this.streamFromArrayAdapters.set(key, sym);
|
|
9481
|
+
const B = new BlockBuilder();
|
|
9482
|
+
const unionDef = elem.kind === "union"
|
|
9483
|
+
? this.unionsById.get(elem.unionId)
|
|
9484
|
+
: undefined;
|
|
9485
|
+
if (elem.kind === "union" && !unionDef) {
|
|
9486
|
+
throw new Error(`llvm emitter bug: streamFrom of unknown union ${elem.unionId}`);
|
|
9487
|
+
}
|
|
9488
|
+
const unionRefArms = unionDef?.arms
|
|
9489
|
+
.map((arm, tag) => ({ arm, tag }))
|
|
9490
|
+
.filter(({ arm }) => isRefCounted(arm) && arm.kind !== "dyn" && arm.kind !== "string") ?? [];
|
|
9491
|
+
const typedRef = isRefCounted(elem) &&
|
|
9492
|
+
elem.kind !== "dyn" &&
|
|
9493
|
+
elem.kind !== "string" &&
|
|
9494
|
+
elem.kind !== "union";
|
|
9495
|
+
const snapshot = `${sym}_materialize`;
|
|
9496
|
+
let value;
|
|
9497
|
+
if (elem.kind === "f64") {
|
|
9498
|
+
this.declare(`declare double @scr_arr_get_f64(ptr, double)`);
|
|
9499
|
+
value = B.tmp();
|
|
9500
|
+
B.line(`${value} = call double @scr_arr_get_f64(ptr %a, double %i)`);
|
|
9501
|
+
}
|
|
9502
|
+
else if (elem.kind === "bool") {
|
|
9503
|
+
this.declare(`declare zeroext i1 @scr_arr_get_bool(ptr, double)`);
|
|
9504
|
+
value = B.tmp();
|
|
9505
|
+
B.line(`${value} = call i1 @scr_arr_get_bool(ptr %a, double %i)`);
|
|
9506
|
+
}
|
|
9507
|
+
else {
|
|
9508
|
+
this.declare(`declare ptr @scr_arr_get_ref(ptr, double)`);
|
|
9509
|
+
value = B.tmp();
|
|
9510
|
+
B.line(`${value} = call ptr @scr_arr_get_ref(ptr %a, double %i) ; +1`);
|
|
9511
|
+
}
|
|
9512
|
+
let boxed;
|
|
9513
|
+
const valueTy = elem.kind === "f64" ? "double" : elem.kind === "bool" ? "i1" : "ptr";
|
|
9514
|
+
if (elem.kind === "union") {
|
|
9515
|
+
if (unionRefArms.length === 0) {
|
|
9516
|
+
boxed = B.tmp();
|
|
9517
|
+
B.line(`${boxed} = call ptr @${this.dyn.toDynHelper(elem)}(ptr ${value})`);
|
|
9518
|
+
}
|
|
9519
|
+
else {
|
|
9520
|
+
this.declare(`declare ptr @scr_dyn_new_typed_ref(ptr, ptr, ptr, ptr, i64, ptr, ptr)`);
|
|
9521
|
+
const boxedSlot = B.slot();
|
|
9522
|
+
B.entryAllocas.push(`${boxedSlot} = alloca ptr`);
|
|
9523
|
+
const tagPtr = B.tmp();
|
|
9524
|
+
const tagValue = B.tmp();
|
|
9525
|
+
B.line(`${tagPtr} = getelementptr inbounds %ScrUnion, ptr ${value}, i64 0, i32 1`);
|
|
9526
|
+
B.line(`${tagValue} = load i32, ptr ${tagPtr}`);
|
|
9527
|
+
const fallback = B.newLabel("sfa.union.dyn");
|
|
9528
|
+
const join = B.newLabel("sfa.union.join");
|
|
9529
|
+
const armLabels = unionRefArms.map(() => B.newLabel("sfa.union.ref"));
|
|
9530
|
+
B.terminate(`switch i32 ${tagValue}, label %${fallback} [ ${unionRefArms.map(({ tag }, i) => `i32 ${tag}, label %${armLabels[i]}`).join(" ")} ]`);
|
|
9531
|
+
unionRefArms.forEach(({ arm, tag }, i) => {
|
|
9532
|
+
const armKey = typeKey(arm);
|
|
9533
|
+
const armSnapshot = `${snapshot}_${tag}`;
|
|
9534
|
+
const armCommit = this.streamTypedRefCommitAdapter(arm, armSnapshot);
|
|
9535
|
+
const rc = vAdapters(this, arm);
|
|
9536
|
+
B.startBlock(armLabels[i]);
|
|
9537
|
+
const payloadPtr = B.tmp();
|
|
9538
|
+
const payload = B.tmp();
|
|
9539
|
+
const armBoxed = B.tmp();
|
|
9540
|
+
B.line(`${payloadPtr} = getelementptr inbounds %ScrUnion, ptr ${value}, i64 0, i32 5`);
|
|
9541
|
+
B.line(`${payload} = load ptr, ptr ${payloadPtr}`);
|
|
9542
|
+
B.line(`${armBoxed} = call ptr @scr_dyn_new_typed_ref(ptr ${payload}, ptr ${rc.retain}, ptr ${rc.release}, ptr ${this.cstr(armKey)}, i64 ${Buffer.byteLength(armKey, "utf8")}, ptr @${armSnapshot}, ptr ${armCommit})`);
|
|
9543
|
+
B.line(`store ptr ${armBoxed}, ptr ${boxedSlot}`);
|
|
9544
|
+
B.br(join);
|
|
9545
|
+
this.resolveThunkDefs.push(`define internal ptr @${armSnapshot}(ptr %p) ${FN_ATTRS} { ; materialize stream union arm ${armKey}`, `entry:`, ` %d = call ptr @${this.dyn.toDynHelper(arm)}(ptr %p)`, ` ret ptr %d`, `}`, ``);
|
|
9546
|
+
});
|
|
9547
|
+
B.startBlock(fallback);
|
|
9548
|
+
const dynBoxed = B.tmp();
|
|
9549
|
+
B.line(`${dynBoxed} = call ptr @${this.dyn.toDynHelper(elem)}(ptr ${value})`);
|
|
9550
|
+
B.line(`store ptr ${dynBoxed}, ptr ${boxedSlot}`);
|
|
9551
|
+
B.br(join);
|
|
9552
|
+
B.startBlock(join);
|
|
9553
|
+
boxed = B.tmp();
|
|
9554
|
+
B.line(`${boxed} = load ptr, ptr ${boxedSlot}`);
|
|
9555
|
+
}
|
|
9556
|
+
}
|
|
9557
|
+
else if (typedRef) {
|
|
9558
|
+
boxed = B.tmp();
|
|
9559
|
+
const rc = vAdapters(this, elem);
|
|
9560
|
+
const keyPtr = this.cstr(key);
|
|
9561
|
+
let commit;
|
|
9562
|
+
if (this.streamTypedRefEligible(elem)) {
|
|
9563
|
+
commit = this.streamTypedRefMaterializeAdapter(elem, { prefix: snapshot, adapters: new Map() }, snapshot).commit;
|
|
9564
|
+
}
|
|
9565
|
+
else {
|
|
9566
|
+
commit = this.streamTypedRefCommitAdapter(elem, snapshot);
|
|
9567
|
+
this.resolveThunkDefs.push(`define internal ptr @${snapshot}(ptr %p) ${FN_ATTRS} { ; materialize stream element ${key}`, `entry:`, ` %d = call ptr @${this.dyn.toDynHelper(elem)}(ptr %p)`, ` ret ptr %d`, `}`, ``);
|
|
9568
|
+
}
|
|
9569
|
+
this.declare(`declare ptr @scr_dyn_new_typed_ref(ptr, ptr, ptr, ptr, i64, ptr, ptr)`);
|
|
9570
|
+
B.line(`${boxed} = call ptr @scr_dyn_new_typed_ref(ptr ${value}, ptr ${rc.retain}, ptr ${rc.release}, ptr ${keyPtr}, i64 ${Buffer.byteLength(key, "utf8")}, ptr @${snapshot}, ptr ${commit})`);
|
|
9571
|
+
}
|
|
9572
|
+
else {
|
|
9573
|
+
boxed = B.tmp();
|
|
9574
|
+
B.line(`${boxed} = call ptr @${this.dyn.toDynHelper(elem)}(${valueTy} ${value})`);
|
|
9575
|
+
}
|
|
9576
|
+
if (isRefCounted(elem)) {
|
|
9577
|
+
B.line(`call void ${releaseSym(this, elem)}(ptr ${value})`);
|
|
9578
|
+
}
|
|
9579
|
+
B.terminate(`ret ptr ${boxed}`);
|
|
9580
|
+
this.resolveThunkDefs.push(`define internal ptr @${sym}(ptr %a, double %i) ${FN_ATTRS} { ; ReadableStream.from array<${key}>`, B.render(), `}`, ``);
|
|
9581
|
+
return sym;
|
|
9582
|
+
}
|
|
9122
9583
|
/** The claimed libCall slice: args are BORROWED (owned temps of the
|
|
9123
9584
|
* current frame), refcounted results come back +1. LLVM types derive
|
|
9124
9585
|
* from the call site's IR types (exactly the contract the C prototypes
|
|
@@ -9131,6 +9592,70 @@ class LlEmitter {
|
|
|
9131
9592
|
// Loop liveness first (one table for generic and special shapes).
|
|
9132
9593
|
if (USES_TIMERS_LIB_FNS.has(e.fn))
|
|
9133
9594
|
this.usesTimers = true;
|
|
9595
|
+
if (e.fn === "fetch.responseText" || e.fn === "fetch.responseBytes") {
|
|
9596
|
+
if (e.type.kind !== "promise") {
|
|
9597
|
+
throw new Error(`llvm emitter bug: ${e.fn} result`);
|
|
9598
|
+
}
|
|
9599
|
+
const response = this.emitExpr(e.args[0]);
|
|
9600
|
+
const runtimeFn = e.fn === "fetch.responseText"
|
|
9601
|
+
? "scr_fetch_response_text"
|
|
9602
|
+
: "scr_fetch_response_bytes";
|
|
9603
|
+
this.declare(`declare ptr @${runtimeFn}(ptr)`);
|
|
9604
|
+
this.declare(`declare ptr @scr_promise_new()`);
|
|
9605
|
+
this.declare(`declare void @scr_promise_race_add(ptr, ptr, ptr)`);
|
|
9606
|
+
const sourceRaw = B.tmp();
|
|
9607
|
+
B.line(`${sourceRaw} = call ptr @${runtimeFn}(ptr ${response.name})`);
|
|
9608
|
+
const source = this.own({
|
|
9609
|
+
name: sourceRaw,
|
|
9610
|
+
type: { kind: "promise", inner: DYN },
|
|
9611
|
+
});
|
|
9612
|
+
const resultRaw = B.tmp();
|
|
9613
|
+
B.line(`${resultRaw} = call ptr @scr_promise_new()`);
|
|
9614
|
+
const result = this.own({ name: resultRaw, type: e.type });
|
|
9615
|
+
B.line(`call void @scr_promise_race_add(ptr ${result.name}, ptr ${source.name}, ptr @${this.dynPromiseAdapter(e.type.inner)})`);
|
|
9616
|
+
return result;
|
|
9617
|
+
}
|
|
9618
|
+
if (e.fn === "fetch.readerRead") {
|
|
9619
|
+
if (e.type.kind !== "promise" || e.type.inner.kind !== "record") {
|
|
9620
|
+
throw new Error("llvm emitter bug: fetch.readerRead result");
|
|
9621
|
+
}
|
|
9622
|
+
const reader = this.emitExpr(e.args[0]);
|
|
9623
|
+
this.declare(`declare ptr @scr_fetch_reader_read(ptr)`);
|
|
9624
|
+
this.declare(`declare ptr @scr_promise_new()`);
|
|
9625
|
+
this.declare(`declare void @scr_promise_race_add(ptr, ptr, ptr)`);
|
|
9626
|
+
const sourceRaw = B.tmp();
|
|
9627
|
+
B.line(`${sourceRaw} = call ptr @scr_fetch_reader_read(ptr ${reader.name})`);
|
|
9628
|
+
const source = this.own({
|
|
9629
|
+
name: sourceRaw,
|
|
9630
|
+
type: { kind: "promise", inner: DYN },
|
|
9631
|
+
});
|
|
9632
|
+
const resultRaw = B.tmp();
|
|
9633
|
+
B.line(`${resultRaw} = call ptr @scr_promise_new()`);
|
|
9634
|
+
const result = this.own({ name: resultRaw, type: e.type });
|
|
9635
|
+
B.line(`call void @scr_promise_race_add(ptr ${result.name}, ptr ${source.name}, ptr @${this.dynPromiseAdapter(e.type.inner)})`);
|
|
9636
|
+
return result;
|
|
9637
|
+
}
|
|
9638
|
+
if (e.fn === "fetch.streamFrom") {
|
|
9639
|
+
const source = this.emitExpr(e.args[0]);
|
|
9640
|
+
let sym = "scr_fetch_stream_from";
|
|
9641
|
+
let extra = "";
|
|
9642
|
+
if (source.type.kind === "array") {
|
|
9643
|
+
sym = "scr_fetch_stream_from_array";
|
|
9644
|
+
extra = `, ptr @${this.streamFromArrayAdapter(source.type)}`;
|
|
9645
|
+
}
|
|
9646
|
+
else if (source.type.kind === "bytes") {
|
|
9647
|
+
sym = "scr_fetch_stream_from_bytes";
|
|
9648
|
+
}
|
|
9649
|
+
else if (source.type.kind === "string") {
|
|
9650
|
+
sym = "scr_fetch_stream_from_string";
|
|
9651
|
+
}
|
|
9652
|
+
this.declare(`declare ptr @${sym}(ptr${source.type.kind === "array" ? ", ptr" : ""})`);
|
|
9653
|
+
const raw = B.tmp();
|
|
9654
|
+
B.line(`${raw} = call ptr @${sym}(ptr ${source.name}${extra})`);
|
|
9655
|
+
const out = this.own({ name: raw, type: e.type });
|
|
9656
|
+
this.emitPendingCheck();
|
|
9657
|
+
return out;
|
|
9658
|
+
}
|
|
9134
9659
|
// The handful with non-generic shapes first.
|
|
9135
9660
|
if (e.fn === "error.argTypeThrow") {
|
|
9136
9661
|
// Always throws with the runtime-rendered Received tail (the
|