@scriptc/compiler 0.0.10 → 0.0.12
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 +63 -15
- package/ambient/scriptc.d.ts +2 -2
- package/dist/backend/cc.d.ts +2 -2
- package/dist/backend/emission/emit-async.js +1 -1
- package/dist/backend/emission/emit-exprs.js +131 -54
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-island.js +1 -1
- package/dist/backend/emission/emit-shapes.js +1 -1
- package/dist/backend/emission/emit-walkers.d.ts +14 -14
- package/dist/backend/emission/emit-walkers.js +44 -44
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.d.ts +3 -3
- package/dist/backend/emission/emitter.js +33 -9
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/emission/may-throw.js +1 -1
- package/dist/backend/llvm/dyn.d.ts +10 -10
- package/dist/backend/llvm/dyn.js +26 -26
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +156 -47
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/backend/llvm/shapes.js +1 -1
- package/dist/backend/llvm/walkers.js +2 -2
- package/dist/backend/llvm/walkers.js.map +1 -1
- package/dist/coverage/surface-manifest.js +16 -2
- package/dist/coverage/surface-manifest.js.map +1 -1
- package/dist/diagnostics/diagnostic.d.ts +21 -8
- package/dist/diagnostics/diagnostic.js +48 -14
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.js +5 -5
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-assert.js +12 -12
- package/dist/frontend/lowering/lower-assert.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +63 -7
- package/dist/frontend/lowering/lower-builtins.js +327 -35
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +4 -4
- package/dist/frontend/lowering/lower-calls.js +104 -70
- package/dist/frontend/lowering/lower-calls.js.map +1 -1
- package/dist/frontend/lowering/lower-classes.d.ts +7 -0
- package/dist/frontend/lowering/lower-classes.js +82 -6
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +9 -5
- package/dist/frontend/lowering/lower-containers.js +88 -26
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-emitter.d.ts +70 -3
- package/dist/frontend/lowering/lower-emitter.js +438 -31
- package/dist/frontend/lowering/lower-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +87 -12
- package/dist/frontend/lowering/lower-exprs.js +630 -125
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-inspect.js +5 -5
- package/dist/frontend/lowering/lower-inspect.js.map +1 -1
- package/dist/frontend/lowering/lower-island.js +12 -3
- package/dist/frontend/lowering/lower-island.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +8 -5
- package/dist/frontend/lowering/lower-modules.js +157 -63
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +24 -0
- package/dist/frontend/lowering/lower-namespaces.js +158 -16
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.js +11 -11
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +1 -1
- package/dist/frontend/lowering/lower-stmts.js +271 -36
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +171 -20
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +27 -10
- package/dist/frontend/lowering/lowerer.js +156 -54
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +44 -0
- package/dist/frontend/lowering/surfaces.js +236 -5
- package/dist/frontend/lowering/surfaces.js.map +1 -1
- package/dist/frontend/npm.d.ts +12 -0
- package/dist/frontend/npm.js +30 -0
- package/dist/frontend/npm.js.map +1 -1
- package/dist/frontend/program.d.ts +25 -0
- package/dist/frontend/program.js +145 -136
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/shared.d.ts +1 -1
- package/dist/frontend/shared.js +8 -8
- package/dist/frontend/shared.js.map +1 -1
- package/dist/frontend/types.d.ts +2 -2
- package/dist/frontend/types.js +15 -15
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +169 -5
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +174 -106
- package/dist/ir/nodes.js +69 -24
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +55 -36
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/fence-eval.js +12 -2
- package/dist/library/fence-eval.js.map +1 -1
- package/dist/library/int-infer.d.ts +119 -0
- package/dist/library/int-infer.js +1314 -0
- package/dist/library/int-infer.js.map +1 -0
- package/dist/library/int-infer.test.d.ts +1 -0
- package/dist/library/int-infer.test.js +279 -0
- package/dist/library/int-infer.test.js.map +1 -0
- package/dist/library/profile.d.ts +34 -5
- package/dist/library/profile.js +77 -13
- package/dist/library/profile.js.map +1 -1
- package/dist/library/sidecar-validate.js +1 -1
- package/dist/library/sidecar-validate.js.map +1 -1
- package/dist/library/sidecar.d.ts +24 -1
- package/dist/library/sidecar.js +163 -16
- package/dist/library/sidecar.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +210 -12
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { canMarshalFuncIntoIsland, CAUGHT, DYN, F64, islandCallbackRet, 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, 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";
|
|
@@ -340,7 +340,7 @@ const LIB_FN_SYMS = {
|
|
|
340
340
|
"sym.toString": "scr_sym_to_string",
|
|
341
341
|
"error.toString": "scr_error_to_string",
|
|
342
342
|
"class.name": "scr_classobj_name",
|
|
343
|
-
// The dyn (ScrDyn
|
|
343
|
+
// The dyn (ScrDyn dyn) surface (scr_json.c / scr_dyn_invoke.c):
|
|
344
344
|
// json.parse throws the catchable SyntaxError; keySet/toString/
|
|
345
345
|
// defineProps throw Node's TypeErrors (all in the may-throw seed set —
|
|
346
346
|
// the generic path emits the standard pending check). typeof and the
|
|
@@ -348,6 +348,8 @@ const LIB_FN_SYMS = {
|
|
|
348
348
|
"json.parse": "scr_json_parse",
|
|
349
349
|
"dyn.keySet": "scr_dyn_key_set",
|
|
350
350
|
"dyn.iterPack": "scr_dyn_iter_pack",
|
|
351
|
+
"dyn.arrLen": "scr_dyn_arr_len",
|
|
352
|
+
"dyn.arrAt": "scr_dyn_arr_at",
|
|
351
353
|
"dyn.defineProps": "scr_dyn_define_props",
|
|
352
354
|
"dyn.typeof": "scr_dyn_typeof",
|
|
353
355
|
"dyn.toString": "scr_dyn_to_string_method",
|
|
@@ -403,6 +405,8 @@ const LIB_FN_SYMS = {
|
|
|
403
405
|
// generic pending check; loop liveness rides USES_TIMERS_LIB_FNS.
|
|
404
406
|
"readable.push": "scr_stream_push",
|
|
405
407
|
"readable.pushStr": "scr_stream_push_str",
|
|
408
|
+
"readable.pushStrEnc": "scr_stream_push_str_enc",
|
|
409
|
+
"readable.pushEncoding": "scr_stream_set_push_encoding",
|
|
406
410
|
"readable.pushNull": "scr_stream_push_null",
|
|
407
411
|
"readable.pushDyn": "scr_stream_push_dyn",
|
|
408
412
|
"readable.unshift": "scr_stream_unshift",
|
|
@@ -504,6 +508,11 @@ const LIB_FN_SYMS = {
|
|
|
504
508
|
// stream/promises' finished form (+1 promise; may-throw pending check;
|
|
505
509
|
// the pipeline form needs the stream-array compound and emits below).
|
|
506
510
|
"sp.finished": "scr_sp_finished",
|
|
511
|
+
// stream/consumers' promise consumers (+1 promises; may-throw pending
|
|
512
|
+
// check — the 'newListener' meta emit can run user code).
|
|
513
|
+
"sc.text": "scr_sc_text",
|
|
514
|
+
"sc.json": "scr_sc_json",
|
|
515
|
+
"sc.buffer": "scr_sc_buffer",
|
|
507
516
|
"dc.channel": "scr_dc_channel",
|
|
508
517
|
"dc.subscribe": "scr_dc_subscribe",
|
|
509
518
|
"dc.unsubscribe": "scr_dc_unsubscribe",
|
|
@@ -528,7 +537,7 @@ const LIB_FN_SYMS = {
|
|
|
528
537
|
"dc.tcTraceCallback": "scr_dc_tc_trace_callback",
|
|
529
538
|
"dc.tcTracePromise": "scr_dc_tc_trace_promise",
|
|
530
539
|
// AsyncLocalStorage (scr_async_dyn.c): store ids are doubles, values
|
|
531
|
-
// ride the
|
|
540
|
+
// ride the checked-dynamic tree; run/exitRun dispatch user callbacks (may-throw).
|
|
532
541
|
// The dc bind-store trio shares the als id space.
|
|
533
542
|
"als.new": "scr_als_new",
|
|
534
543
|
"als.get": "scr_als_get",
|
|
@@ -540,7 +549,7 @@ const LIB_FN_SYMS = {
|
|
|
540
549
|
"dc.chanUnbindStore": "scr_dc_chan_unbind_store",
|
|
541
550
|
"dc.chanRunStores": "scr_dc_chan_run_stores",
|
|
542
551
|
// process warning/rejection events (scr_lib.c / scr_async_dyn.c):
|
|
543
|
-
//
|
|
552
|
+
// dyn listeners are borrowed (the runtime retains its copy);
|
|
544
553
|
// onUnhandledRejection marks the loop live (the loop-end report
|
|
545
554
|
// dispatches the listeners).
|
|
546
555
|
"process.onWarning": "scr_process_on_warning",
|
|
@@ -561,7 +570,7 @@ const LIB_FN_SYMS = {
|
|
|
561
570
|
"regexp.escape": "scr_regexp_escape",
|
|
562
571
|
// The dyn Object walks (throw on nullish receivers), structuredClone
|
|
563
572
|
// (option/DataClone/cycle errors), and new RegExp's eager compile
|
|
564
|
-
// (catchable SyntaxError) — all may-throw generics over the
|
|
573
|
+
// (catchable SyntaxError) — all may-throw generics over the checked-dynamic tree.
|
|
565
574
|
"dyn.objKeys": "scr_dyn_obj_keys",
|
|
566
575
|
"dyn.hasOwn": "scr_dyn_has_own",
|
|
567
576
|
"dyn.assign": "scr_dyn_assign",
|
|
@@ -604,7 +613,8 @@ const USES_TIMERS_LIB_FNS = new Set([
|
|
|
604
613
|
"readable.init", "writable.init", "duplex.init", "transform.init", "passthrough.init",
|
|
605
614
|
"readable.newDyn", "writable.newDyn", "duplex.newDyn", "transform.newDyn", "passthrough.newDyn",
|
|
606
615
|
"readable.initDyn", "writable.initDyn", "duplex.initDyn", "transform.initDyn", "passthrough.initDyn",
|
|
607
|
-
"readable.push", "readable.pushStr", "readable.
|
|
616
|
+
"readable.push", "readable.pushStr", "readable.pushStrEnc", "readable.pushEncoding",
|
|
617
|
+
"readable.pushNull", "readable.pushU", "readable.pushDyn",
|
|
608
618
|
"readable.unshift", "readable.unshiftStr", "readable.read", "readable.setEncoding",
|
|
609
619
|
"readable.nextChunk", "readable.nextChunkDyn", "readable.fromArr", "readable.resume",
|
|
610
620
|
"readable.pipe", "readable.unpipe",
|
|
@@ -616,6 +626,7 @@ const USES_TIMERS_LIB_FNS = new Set([
|
|
|
616
626
|
"process.activeResources",
|
|
617
627
|
"stream.finished", "stream.finishedDyn", "stream.pipeline", "stream.pipelineDyn",
|
|
618
628
|
"sp.finished", "sp.pipeline",
|
|
629
|
+
"sc.text", "sc.json", "sc.buffer",
|
|
619
630
|
"net.listen", "net.listenCb", "net.listenOpts", "net.listenOptsCb",
|
|
620
631
|
"net.connect", "net.connectCb", "net.connectLookup", "net.connectAttempt",
|
|
621
632
|
"fs.existsChk",
|
|
@@ -710,7 +721,7 @@ class LlEmitter {
|
|
|
710
721
|
* rewriter, union ToString/join) — interned per typeKey/unionId, defs
|
|
711
722
|
* flushed with the shape helpers. */
|
|
712
723
|
walkers = new LlWalkers(this);
|
|
713
|
-
/** The dyn (ScrDyn
|
|
724
|
+
/** The dyn (ScrDyn dyn) helper registry — dyn.ts's interned ports of
|
|
714
725
|
* emit-walkers.ts's dyn slice. */
|
|
715
726
|
dyn = new LlDyn(this);
|
|
716
727
|
/** External declarations, in first-use order. */
|
|
@@ -1070,6 +1081,12 @@ class LlEmitter {
|
|
|
1070
1081
|
if (this.mod.lib.exports.some((e) => e.params.includes("bytes"))) {
|
|
1071
1082
|
this.declare(`declare ptr @scr_library_bytes_in(ptr, i64, ptr)`);
|
|
1072
1083
|
}
|
|
1084
|
+
if (this.mod.lib.exports.some((e) => e.params.includes("i64"))) {
|
|
1085
|
+
this.declare(`declare double @scr_library_i64_in(i64, ptr)`);
|
|
1086
|
+
}
|
|
1087
|
+
if (this.mod.lib.exports.some((e) => e.params.includes("u64"))) {
|
|
1088
|
+
this.declare(`declare double @scr_library_u64_in(i64, ptr)`);
|
|
1089
|
+
}
|
|
1073
1090
|
if (this.mod.lib.exports.some((e) => e.returns === "string")) {
|
|
1074
1091
|
this.declare(`declare void @scr_library_str_out(ptr, ptr, ptr)`);
|
|
1075
1092
|
}
|
|
@@ -1378,6 +1395,14 @@ class LlEmitter {
|
|
|
1378
1395
|
const trapBytes = Buffer.byteLength(e.inboundBytesTrap, "utf8");
|
|
1379
1396
|
out.push(`@sc_lib_bytes_trap_${e.symbol} = internal constant [${trapBytes + 1} x i8] c"${llStrBytes(e.inboundBytesTrap)}"`, ``);
|
|
1380
1397
|
}
|
|
1398
|
+
if (e.inboundIntTrap !== undefined) {
|
|
1399
|
+
// The i64/u64-in helpers' host-contract trap message (ask 4): an
|
|
1400
|
+
// inbound integer past ±(2^53−1) cannot ride f64 exactly. Same
|
|
1401
|
+
// assembled structured form, same SC4012 code, same
|
|
1402
|
+
// emission-invariance argument as the bytes trap.
|
|
1403
|
+
const trapBytes = Buffer.byteLength(e.inboundIntTrap, "utf8");
|
|
1404
|
+
out.push(`@sc_lib_int_trap_${e.symbol} = internal constant [${trapBytes + 1} x i8] c"${llStrBytes(e.inboundIntTrap)}"`, ``);
|
|
1405
|
+
}
|
|
1381
1406
|
e.params.forEach((cls, i) => {
|
|
1382
1407
|
switch (cls) {
|
|
1383
1408
|
case "f64":
|
|
@@ -1404,6 +1429,19 @@ class LlEmitter {
|
|
|
1404
1429
|
body.push(` %c${i} = sitofp i32 %a${i} to double`);
|
|
1405
1430
|
args.push(`double %c${i}`);
|
|
1406
1431
|
break;
|
|
1432
|
+
case "i64":
|
|
1433
|
+
// Inbound declared-integer edge (ask 4): the helper converts
|
|
1434
|
+
// exactly or delivers the host-contract trap (past ±(2^53−1)
|
|
1435
|
+
// the value cannot ride f64 without silent rounding).
|
|
1436
|
+
params.push(`i64 %a${i}`);
|
|
1437
|
+
body.push(` %c${i} = call double @scr_library_i64_in(i64 %a${i}, ptr @sc_lib_int_trap_${e.symbol})`);
|
|
1438
|
+
args.push(`double %c${i}`);
|
|
1439
|
+
break;
|
|
1440
|
+
case "u64":
|
|
1441
|
+
params.push(`i64 %a${i}`);
|
|
1442
|
+
body.push(` %c${i} = call double @scr_library_u64_in(i64 %a${i}, ptr @sc_lib_int_trap_${e.symbol})`);
|
|
1443
|
+
args.push(`double %c${i}`);
|
|
1444
|
+
break;
|
|
1407
1445
|
case "string":
|
|
1408
1446
|
params.push(`ptr %a${i}_ptr`, `i64 %a${i}_len`);
|
|
1409
1447
|
body.push(` %c${i} = call ptr @scr_library_str_in(ptr %a${i}_ptr, i64 %a${i}_len)`);
|
|
@@ -1430,6 +1468,16 @@ class LlEmitter {
|
|
|
1430
1468
|
retType = "double";
|
|
1431
1469
|
body.push(` %r = call double ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` ret double %r`);
|
|
1432
1470
|
break;
|
|
1471
|
+
case "i64":
|
|
1472
|
+
case "u64":
|
|
1473
|
+
// The outbound declared-integer edge (ask 4): every value
|
|
1474
|
+
// reaching this return was PROVEN whole and inside the class's
|
|
1475
|
+
// range at compile time, so the fp-to-int conversion is exact
|
|
1476
|
+
// by construction — the crossing carries the mathematically
|
|
1477
|
+
// exact integer the f64 held.
|
|
1478
|
+
retType = "i64";
|
|
1479
|
+
body.push(` %r = call double ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` %z = ${e.returns === "i64" ? "fptosi" : "fptoui"} double %r to i64`, ` ret i64 %z`);
|
|
1480
|
+
break;
|
|
1433
1481
|
case "bool":
|
|
1434
1482
|
retType = "i8";
|
|
1435
1483
|
body.push(` %r = call i1 ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` %z = zext i1 %r to i8`, ` ret i8 %z`);
|
|
@@ -1990,7 +2038,7 @@ class LlEmitter {
|
|
|
1990
2038
|
return t;
|
|
1991
2039
|
}
|
|
1992
2040
|
case "dyn": {
|
|
1993
|
-
// ToBoolean over the
|
|
2041
|
+
// ToBoolean over the dyn kind (scr_dyn_truthy — JS-exact for
|
|
1994
2042
|
// every kind; borrowed, never throws): `v || dflt` and condition
|
|
1995
2043
|
// descent on checked-dynamic values.
|
|
1996
2044
|
this.declare(`declare zeroext i1 @scr_dyn_truthy(ptr)`);
|
|
@@ -3668,7 +3716,7 @@ class LlEmitter {
|
|
|
3668
3716
|
return this.own({ name: t, type: e.type });
|
|
3669
3717
|
}
|
|
3670
3718
|
if (v.type.kind === "dyn") {
|
|
3671
|
-
// String(unknown): dispatch over the
|
|
3719
|
+
// String(unknown): dispatch over the dyn kind (dyn.ts's sc_ds —
|
|
3672
3720
|
// Node's String() incl. arrays-join and "[object Object]").
|
|
3673
3721
|
const helper = this.dyn.dynToStrHelper();
|
|
3674
3722
|
const t = B.tmp();
|
|
@@ -3969,7 +4017,7 @@ class LlEmitter {
|
|
|
3969
4017
|
this.unionTagSwitch(u.name, def, (arm) => {
|
|
3970
4018
|
if (isUnitType(arm)) {
|
|
3971
4019
|
if (e.type.kind === "dyn") {
|
|
3972
|
-
// A dyn-typed chain: the unit path is the undefined
|
|
4020
|
+
// A dyn-typed chain: the unit path is the undefined dyn
|
|
3973
4021
|
// value — dyn represents undefined directly.
|
|
3974
4022
|
this.declare(`declare ptr @scr_dyn_undefined()`);
|
|
3975
4023
|
this.declare(`declare ptr @scr_dyn_retain_v(ptr)`);
|
|
@@ -4265,9 +4313,9 @@ class LlEmitter {
|
|
|
4265
4313
|
// the frame's release is a no-op) and the body reads it through
|
|
4266
4314
|
// chainRecv.
|
|
4267
4315
|
if (e.receiver.type.kind === "dyn") {
|
|
4268
|
-
// A dyn (
|
|
4316
|
+
// A dyn (dyn) receiver — the `rawName?.match(re)` step: the
|
|
4269
4317
|
// nullish test reads the node's kind tag; the unit path is the
|
|
4270
|
-
// undefined
|
|
4318
|
+
// undefined dyn singleton (dyn results) or nothing (void
|
|
4271
4319
|
// bodies), the body runs over the bound receiver otherwise.
|
|
4272
4320
|
const r = this.emitExpr(e.receiver);
|
|
4273
4321
|
const kd = this.dynKind(r.name);
|
|
@@ -4419,7 +4467,7 @@ class LlEmitter {
|
|
|
4419
4467
|
}
|
|
4420
4468
|
if (e.type.kind === "dyn") {
|
|
4421
4469
|
// A dyn-typed chain (`pricing?.[key]` over an unknown-valued
|
|
4422
|
-
// index signature): the unit path is the undefined
|
|
4470
|
+
// index signature): the unit path is the undefined dyn value —
|
|
4423
4471
|
// dyn represents undefined directly, no union wrapper exists.
|
|
4424
4472
|
const slotD = B.slot();
|
|
4425
4473
|
B.entryAllocas.push(`${slotD} = alloca ptr`);
|
|
@@ -4866,14 +4914,14 @@ class LlEmitter {
|
|
|
4866
4914
|
}
|
|
4867
4915
|
case "jsonStringify": {
|
|
4868
4916
|
// Type-directed serialization: the STATIC type picks an emitted
|
|
4869
|
-
// serializer (interned per typeKey) — no
|
|
4917
|
+
// serializer (interned per typeKey) — no dyn, no runtime dispatch.
|
|
4870
4918
|
// The value temp is BORROWED (released with this statement's
|
|
4871
4919
|
// frame); the result string is owned (+1). Never throws — except
|
|
4872
4920
|
// the dyn root below.
|
|
4873
4921
|
const v = this.emitExpr(e.value);
|
|
4874
4922
|
let compact;
|
|
4875
4923
|
if (e.value.type.kind === "dyn") {
|
|
4876
|
-
// A dyn root: the runtime's
|
|
4924
|
+
// A dyn root: the runtime's dyn walker (scr_dyn_format_j — the
|
|
4877
4925
|
// C backend's dispatch exactly): number/string/bool/null/array/
|
|
4878
4926
|
// object exact, dropped members omitted, and a dropped ROOT
|
|
4879
4927
|
// becomes the TEXT "undefined" (JSON.stringify(undefined) is
|
|
@@ -5038,7 +5086,7 @@ class LlEmitter {
|
|
|
5038
5086
|
if (e.arg === null) {
|
|
5039
5087
|
if (genT.nextT.kind === "dyn") {
|
|
5040
5088
|
// Valueless resume on a dyn channel: JS's undefined — the
|
|
5041
|
-
//
|
|
5089
|
+
// dyn singleton rides the IN slot (+1 moves in).
|
|
5042
5090
|
this.declare(`declare ptr @scr_dyn_undefined()`);
|
|
5043
5091
|
this.declare(`declare ptr @scr_dyn_retain_v(ptr)`);
|
|
5044
5092
|
this.declare(`declare void @scr_dyn_release_v(ptr)`);
|
|
@@ -5506,10 +5554,10 @@ class LlEmitter {
|
|
|
5506
5554
|
return { name: "", type: e.type };
|
|
5507
5555
|
}
|
|
5508
5556
|
case "dynFrom": {
|
|
5509
|
-
// Static value → fresh
|
|
5557
|
+
// Static value → fresh dyn tree (+1) through the interned per-type
|
|
5510
5558
|
// converter; the operand stays borrowed (frame-released as usual).
|
|
5511
5559
|
// Bare unit literals (an `undefined`/`null` stored under an
|
|
5512
|
-
// `unknown` index signature) are the
|
|
5560
|
+
// `unknown` index signature) are the dyn unit values directly.
|
|
5513
5561
|
if (e.value.kind === "unitLit") {
|
|
5514
5562
|
const t = B.tmp();
|
|
5515
5563
|
if (e.value.unit === "undefined") {
|
|
@@ -5527,7 +5575,7 @@ class LlEmitter {
|
|
|
5527
5575
|
}
|
|
5528
5576
|
const v = this.emitExpr(e.value);
|
|
5529
5577
|
if (v.type.kind === "func") {
|
|
5530
|
-
// A closure boxes as the
|
|
5578
|
+
// A closure boxes as the checked-dynamic tree's function kind: retained closure +
|
|
5531
5579
|
// the per-signature call thunk + the interned signature key. The
|
|
5532
5580
|
// best-effort name rides along (null when the lowering had none).
|
|
5533
5581
|
const name = e.fnName !== undefined && e.fnName !== "" ? this.cstr(e.fnName) : "null";
|
|
@@ -5543,8 +5591,8 @@ class LlEmitter {
|
|
|
5543
5591
|
return this.own({ name: t, type: e.type });
|
|
5544
5592
|
}
|
|
5545
5593
|
case "dynFromJsval": {
|
|
5546
|
-
// Island value →
|
|
5547
|
-
// retains the cell in; engine scalars normalize to native
|
|
5594
|
+
// Island value → dyn: the by-reference wrap (scr_dyn_from_jsval
|
|
5595
|
+
// retains the cell in; engine scalars normalize to native dyn
|
|
5548
5596
|
// kinds at wrap time). Operand borrowed, result +1, never throws.
|
|
5549
5597
|
const v = this.emitExpr(e.value);
|
|
5550
5598
|
this.declare(`declare ptr @scr_dyn_from_jsval(ptr)`);
|
|
@@ -5563,7 +5611,7 @@ class LlEmitter {
|
|
|
5563
5611
|
return this.own({ name: t, type: e.type });
|
|
5564
5612
|
}
|
|
5565
5613
|
case "dynCheck": {
|
|
5566
|
-
// The dynamic boundary: validate the
|
|
5614
|
+
// The dynamic boundary: validate the checked-dynamic tree against the target type
|
|
5567
5615
|
// and BUILD the typed value (+1) — or throw the catchable
|
|
5568
5616
|
// path-annotated TypeError. The dyn temp is BORROWED; the result
|
|
5569
5617
|
// joins the frame BEFORE the pending check so an unwind releases
|
|
@@ -5584,11 +5632,11 @@ class LlEmitter {
|
|
|
5584
5632
|
// spelling rides along for Node's "<name> is not a function".
|
|
5585
5633
|
const callee = this.emitExpr(e.callee);
|
|
5586
5634
|
if (e.spreads !== undefined && e.spreads.length > 0) {
|
|
5587
|
-
// The RUNTIME-ARITY form (`f(...args)`): one fresh
|
|
5635
|
+
// The RUNTIME-ARITY form (`f(...args)`): one fresh dyn array
|
|
5588
5636
|
// collects the arguments left-to-right — plain args move in
|
|
5589
5637
|
// (push takes ownership), spread args FLATTEN (push_spread
|
|
5590
5638
|
// retains elements in and throws V8's spread-call TypeError for
|
|
5591
|
-
// non-iterable
|
|
5639
|
+
// non-iterable dyn kinds, checked per spread — JS's
|
|
5592
5640
|
// ArgumentListEvaluation order) — then apply calls through the
|
|
5593
5641
|
// array's elements (borrowed, exactly scr_dyn_call).
|
|
5594
5642
|
this.declare(`declare ptr @scr_dyn_new_arr()`);
|
|
@@ -5661,7 +5709,7 @@ class LlEmitter {
|
|
|
5661
5709
|
return out;
|
|
5662
5710
|
}
|
|
5663
5711
|
case "dynArrLit": {
|
|
5664
|
-
// A
|
|
5712
|
+
// A dyn array built element-by-element: ownership of each dyn
|
|
5665
5713
|
// element MOVES into the array (scr_dyn_arr_push's contract).
|
|
5666
5714
|
this.declare(`declare ptr @scr_dyn_new_arr()`);
|
|
5667
5715
|
this.declare(`declare void @scr_dyn_arr_push(ptr, ptr)`);
|
|
@@ -5676,7 +5724,7 @@ class LlEmitter {
|
|
|
5676
5724
|
return out;
|
|
5677
5725
|
}
|
|
5678
5726
|
case "dynObjLit": {
|
|
5679
|
-
// A
|
|
5727
|
+
// A dyn object built member-by-member: key then value, source
|
|
5680
5728
|
// order. scr_dyn_key_set BORROWS all three (the member retains the
|
|
5681
5729
|
// value in); the receiver is a fresh OBJ, so the non-object throw
|
|
5682
5730
|
// paths are unreachable here.
|
|
@@ -5693,7 +5741,7 @@ class LlEmitter {
|
|
|
5693
5741
|
return out;
|
|
5694
5742
|
}
|
|
5695
5743
|
case "dynKeyGet": {
|
|
5696
|
-
// Keyed read on the
|
|
5744
|
+
// Keyed read on the checked-dynamic tree through the one interned helper — the
|
|
5697
5745
|
// non-optional form throws JS's TypeError on an undefined/null
|
|
5698
5746
|
// receiver, and HANDLE receivers can throw the loud unmodeled-
|
|
5699
5747
|
// property ladder on EITHER form; the result is owned (+1).
|
|
@@ -5778,7 +5826,7 @@ class LlEmitter {
|
|
|
5778
5826
|
const [d, s, st] = e.left.type.kind === "dyn" ? [l, r, e.right.type] : [r, l, e.left.type];
|
|
5779
5827
|
let test;
|
|
5780
5828
|
if (st.kind === "dyn") {
|
|
5781
|
-
// dyn vs dyn: whole-
|
|
5829
|
+
// dyn vs dyn: whole-dyn strict equality.
|
|
5782
5830
|
this.declare(`declare zeroext i1 @scr_dyn_strict_eq(ptr, ptr)`);
|
|
5783
5831
|
test = B.tmp();
|
|
5784
5832
|
B.line(`${test} = call zeroext i1 @scr_dyn_strict_eq(ptr ${l.name}, ptr ${r.name})`);
|
|
@@ -5831,7 +5879,7 @@ class LlEmitter {
|
|
|
5831
5879
|
return { name: neg, type: e.type };
|
|
5832
5880
|
}
|
|
5833
5881
|
case "dynTest": {
|
|
5834
|
-
// A pure kind compare on the
|
|
5882
|
+
// A pure kind compare on the dyn node — borrowed; only the truthy
|
|
5835
5883
|
// form also reads a scalar payload (the runtime's ToBoolean).
|
|
5836
5884
|
const d = this.emitExpr(e.value);
|
|
5837
5885
|
let test;
|
|
@@ -5841,7 +5889,7 @@ class LlEmitter {
|
|
|
5841
5889
|
B.line(`${test} = call zeroext i1 @scr_dyn_truthy(ptr ${d.name})`);
|
|
5842
5890
|
}
|
|
5843
5891
|
else if (e.test === "error") {
|
|
5844
|
-
// `u instanceof Error`: the
|
|
5892
|
+
// `u instanceof Error`: the checked-dynamic tree's error encoding — an object
|
|
5845
5893
|
// carrying the reserved "%error" marker key — or a real engine
|
|
5846
5894
|
// Error held by reference (the isl helper answers false for
|
|
5847
5895
|
// every non-JSVAL kind, so the call is unconditional).
|
|
@@ -5908,7 +5956,7 @@ class LlEmitter {
|
|
|
5908
5956
|
test = orIsl(oneOf([DK.OBJ, DK.ARR, DK.BYTES, DK.HANDLE, DK.PROMISE, DK.NULL]), "scr_dyn_isl_typeof_is", this.cstr("object"));
|
|
5909
5957
|
}
|
|
5910
5958
|
else if (e.test === "array") {
|
|
5911
|
-
// Array.isArray: the
|
|
5959
|
+
// Array.isArray: the checked-dynamic tree's array kind, or the engine's own
|
|
5912
5960
|
// answer for an engine-held value.
|
|
5913
5961
|
test = orIsl(oneOf([DK.ARR]), "scr_dyn_isl_is_array");
|
|
5914
5962
|
}
|
|
@@ -5934,7 +5982,7 @@ class LlEmitter {
|
|
|
5934
5982
|
return { name: neg, type: e.type };
|
|
5935
5983
|
}
|
|
5936
5984
|
case "dynDestrCheck": {
|
|
5937
|
-
// RequireObjectCoercible with V8's destructuring TypeError.
|
|
5985
|
+
// RequireObjectCoercible with V8's destructuring TypeError. dyn
|
|
5938
5986
|
// values check in the runtime helper and pass through unchanged
|
|
5939
5987
|
// (same temp, same ownership); island values check in the engine
|
|
5940
5988
|
// (a fresh +1 cell for the same value comes back).
|
|
@@ -5955,7 +6003,7 @@ class LlEmitter {
|
|
|
5955
6003
|
}
|
|
5956
6004
|
case "dynIterN": {
|
|
5957
6005
|
// GetIterator + first-N steps as a fresh array (V8's exact
|
|
5958
|
-
// not-iterable TypeError on non-iterables): the
|
|
6006
|
+
// not-iterable TypeError on non-iterables): the dyn helper for
|
|
5959
6007
|
// dyn operands, the engine's real iterator protocol for island
|
|
5960
6008
|
// ones.
|
|
5961
6009
|
const v = this.emitExpr(e.value);
|
|
@@ -5987,7 +6035,9 @@ class LlEmitter {
|
|
|
5987
6035
|
const v = this.emitExpr(e.value);
|
|
5988
6036
|
const payload = e.type.kind === "promise" && e.type.inner.kind === "void"
|
|
5989
6037
|
? 0 // SCR_ISLP_VOID
|
|
5990
|
-
:
|
|
6038
|
+
: e.type.kind === "promise" && e.type.inner.kind === "array" && e.type.inner.elem.kind === "jsval"
|
|
6039
|
+
? 5 // SCR_ISLP_JSVAL_ARR: the Array.isArray-gated by-reference exit at settle
|
|
6040
|
+
: 4; // SCR_ISLP_JSVAL
|
|
5991
6041
|
this.declare(`declare ptr @scr_jsval_bridge_promise(ptr, i32)`);
|
|
5992
6042
|
const t = B.tmp();
|
|
5993
6043
|
B.line(`${t} = call ptr @scr_jsval_bridge_promise(ptr ${v.name}, i32 ${payload})`);
|
|
@@ -6035,7 +6085,7 @@ class LlEmitter {
|
|
|
6035
6085
|
case "string":
|
|
6036
6086
|
return simple("scr_jsval_from_str", "ptr", false);
|
|
6037
6087
|
case "dyn":
|
|
6038
|
-
// A CHECKED-DYNAMIC (
|
|
6088
|
+
// A CHECKED-DYNAMIC (dyn) value entering the island: deep copy,
|
|
6039
6089
|
// data kinds only — boxed functions/handles/promises throw the
|
|
6040
6090
|
// catchable TypeError in the runtime, and a wrapped island value
|
|
6041
6091
|
// unwraps to the SAME engine value (the identity round trip).
|
|
@@ -6047,6 +6097,25 @@ class LlEmitter {
|
|
|
6047
6097
|
case "url":
|
|
6048
6098
|
// A URL crossing IN: an engine URL instance built from href.
|
|
6049
6099
|
return simple("scr_jsval_from_url", "ptr", true);
|
|
6100
|
+
case "promise": {
|
|
6101
|
+
// A STATIC promise crossing IN: a real engine thenable settled
|
|
6102
|
+
// when the scriptc promise settles (the async-callback return
|
|
6103
|
+
// bridge). from_promise takes ownership of a +1 — retain past
|
|
6104
|
+
// the borrowed frame temp. The C emitter's rule, mirrored.
|
|
6105
|
+
const tag = islandPromisePayloadTag(e.value.type.inner);
|
|
6106
|
+
if (!tag)
|
|
6107
|
+
throw new Error("llvm emitter bug: jsMarshal of a promise outside the bridge payload domain");
|
|
6108
|
+
const tagN = { void: 0, f64: 1, bool: 2, string: 3, jsval: 4, jsvalArr: 5 }[tag];
|
|
6109
|
+
this.declare(`declare ptr @scr_promise_retain(ptr)`);
|
|
6110
|
+
this.declare(`declare ptr @scr_jsval_from_promise(ptr, i32)`);
|
|
6111
|
+
const pr = B.tmp();
|
|
6112
|
+
B.line(`${pr} = call ptr @scr_promise_retain(ptr ${v.name})`);
|
|
6113
|
+
const t = B.tmp();
|
|
6114
|
+
B.line(`${t} = call ptr @scr_jsval_from_promise(ptr ${pr}, i32 ${tagN})`);
|
|
6115
|
+
const out = this.own({ name: t, type: e.type });
|
|
6116
|
+
this.emitPendingCheck();
|
|
6117
|
+
return out;
|
|
6118
|
+
}
|
|
6050
6119
|
case "func": {
|
|
6051
6120
|
// A closure entering the island as a host function: from_closure
|
|
6052
6121
|
// retains it; the engine's finalizer releases it at teardown. The
|
|
@@ -6378,6 +6447,17 @@ class LlEmitter {
|
|
|
6378
6447
|
return out;
|
|
6379
6448
|
}
|
|
6380
6449
|
default: {
|
|
6450
|
+
// `any[]`-declared slot: Array.isArray-gated, elements BY
|
|
6451
|
+
// REFERENCE (identity crosses; the spine is a snapshot copy).
|
|
6452
|
+
// JSON-safe element types keep the round trip below.
|
|
6453
|
+
if (e.type.kind === "array" && e.type.elem.kind === "jsval") {
|
|
6454
|
+
this.declare(`declare ptr @scr_jsval_exit_jsval_arr(ptr)`);
|
|
6455
|
+
const t = B.tmp();
|
|
6456
|
+
B.line(`${t} = call ptr @scr_jsval_exit_jsval_arr(ptr ${v.name})`);
|
|
6457
|
+
const out = this.own({ name: t, type: e.type });
|
|
6458
|
+
this.emitPendingCheck();
|
|
6459
|
+
return out;
|
|
6460
|
+
}
|
|
6381
6461
|
// An undefined-armed union target: the engine's undefined takes
|
|
6382
6462
|
// the undefined arm FIRST (JSON cannot spell it); then null and
|
|
6383
6463
|
// data ride the round trip into the union's dynCheck like any
|
|
@@ -6414,11 +6494,31 @@ class LlEmitter {
|
|
|
6414
6494
|
B.br(lj);
|
|
6415
6495
|
B.startBlock(ld);
|
|
6416
6496
|
this.frames.push([]);
|
|
6417
|
-
const
|
|
6418
|
-
|
|
6419
|
-
|
|
6420
|
-
|
|
6421
|
-
|
|
6497
|
+
const unionDef = this.unionsById.get(e.type.unionId);
|
|
6498
|
+
const dataArms = unionDef ? unionDef.arms.flatMap((a, i) => (isUnitType(a) ? [] : [{ a, i }])) : [];
|
|
6499
|
+
const jsvalArr = dataArms.length === 1 && dataArms[0].a.kind === "array" && dataArms[0].a.elem.kind === "jsval" ? dataArms[0] : null;
|
|
6500
|
+
let t;
|
|
6501
|
+
if (jsvalArr) {
|
|
6502
|
+
// The `any[] | undefined` defaulted-parameter spelling: the
|
|
6503
|
+
// engine array exits BY REFERENCE into the data arm.
|
|
6504
|
+
this.declare(`declare ptr @scr_jsval_exit_jsval_arr(ptr)`);
|
|
6505
|
+
this.declare(`declare ptr @scr_union_new_ref(i32, ptr, ptr, ptr, ptr)`);
|
|
6506
|
+
this.declare(`declare ptr @scr_arr_retain_v(ptr)`);
|
|
6507
|
+
this.declare(`declare void @scr_arr_release_v(ptr)`);
|
|
6508
|
+
const arr = B.tmp();
|
|
6509
|
+
B.line(`${arr} = call ptr @scr_jsval_exit_jsval_arr(ptr ${v.name})`);
|
|
6510
|
+
this.emitPendingCheck();
|
|
6511
|
+
t = B.tmp();
|
|
6512
|
+
B.line(`${t} = call ptr @scr_union_new_ref(i32 ${jsvalArr.i}, ptr ${arr}, ptr @scr_arr_retain_v, ptr @scr_arr_release_v, ptr null)`);
|
|
6513
|
+
B.line(`store ptr ${t}, ptr ${slot}`);
|
|
6514
|
+
}
|
|
6515
|
+
else {
|
|
6516
|
+
t = roundTrip();
|
|
6517
|
+
this.own({ name: t, type: e.type });
|
|
6518
|
+
this.emitPendingCheck();
|
|
6519
|
+
this.moveTemp({ name: t, type: e.type });
|
|
6520
|
+
B.line(`store ptr ${t}, ptr ${slot}`);
|
|
6521
|
+
}
|
|
6422
6522
|
this.releaseFrame(this.frames.pop());
|
|
6423
6523
|
B.br(lj);
|
|
6424
6524
|
B.startBlock(lj);
|
|
@@ -6631,7 +6731,7 @@ class LlEmitter {
|
|
|
6631
6731
|
d.push(` %r = call ptr %fn(${passed.join(", ")})`, ` %rn = icmp eq ptr %r, null`, ` br i1 %rn, label %snull, label %sok`, `snull:`, ` ret ptr null`, `sok:`, ` %j = call ptr @scr_jsval_from_str(ptr %r)`, ` call void @scr_str_release(ptr %r)`, ` ret ptr %j`);
|
|
6632
6732
|
break;
|
|
6633
6733
|
case "dyn":
|
|
6634
|
-
// A checked-dynamic (+1
|
|
6734
|
+
// A checked-dynamic (+1 dyn) result: deep copy into the engine
|
|
6635
6735
|
// (the jsMarshal dyn rule); NULL is the throw-path dummy.
|
|
6636
6736
|
this.declare(`declare ptr @scr_jsval_from_dyn(ptr)`);
|
|
6637
6737
|
this.declare(`declare void @scr_dyn_release(ptr)`);
|
|
@@ -6662,7 +6762,7 @@ class LlEmitter {
|
|
|
6662
6762
|
this.resolveThunkDefs.push(...d);
|
|
6663
6763
|
return sym;
|
|
6664
6764
|
}
|
|
6665
|
-
/** Loads a
|
|
6765
|
+
/** Loads a dyn node's kind tag (i32 at +8) — the dyn expression tests'
|
|
6666
6766
|
* shared read. */
|
|
6667
6767
|
dynKind(d) {
|
|
6668
6768
|
const B = this.B;
|
|
@@ -8255,6 +8355,10 @@ class LlEmitter {
|
|
|
8255
8355
|
return call("scr_bytes_get", "double (ptr, double)", `ptr ${r.name}, double ${args[0].name}`, false, false);
|
|
8256
8356
|
case "slice":
|
|
8257
8357
|
return call("scr_bytes_slice", "ptr (ptr, double, double)", `ptr ${r.name}, double ${args[0]?.name ?? f64Lit(0)}, double ${args[1]?.name ?? F64_INF}`, true, false);
|
|
8358
|
+
case "subarray":
|
|
8359
|
+
// A +1 VIEW aliasing the receiver's storage (subarray / Buffer's
|
|
8360
|
+
// slice); same index defaults as slice.
|
|
8361
|
+
return call("scr_bytes_subarray", "ptr (ptr, double, double)", `ptr ${r.name}, double ${args[0]?.name ?? f64Lit(0)}, double ${args[1]?.name ?? F64_INF}`, true, false);
|
|
8258
8362
|
case "setFrom":
|
|
8259
8363
|
// dst.set(src, offset?) — void; throws Node's RangeError on
|
|
8260
8364
|
// overflow.
|
|
@@ -8308,6 +8412,10 @@ class LlEmitter {
|
|
|
8308
8412
|
B.line(`${t} = fcmp one double ${idx.name}, ${f64Lit(-1)}`);
|
|
8309
8413
|
return { name: t, type: e.type };
|
|
8310
8414
|
}
|
|
8415
|
+
case "fillElem":
|
|
8416
|
+
// Per-element TypedArray fill (non-u8): slice-style index
|
|
8417
|
+
// defaults, never throws; the receiver comes back +1.
|
|
8418
|
+
return call("scr_bytes_fill_elem", "ptr (ptr, double, double, double)", `ptr ${r.name}, double ${args[0].name}, double ${args[1]?.name ?? f64Lit(0)}, double ${args[2]?.name ?? F64_INF}`, true, false);
|
|
8311
8419
|
case "fill":
|
|
8312
8420
|
case "fillNum": {
|
|
8313
8421
|
const sym = method === "fill" ? "scr_bytes_fill" : "scr_bytes_fill_num";
|
|
@@ -8483,7 +8591,7 @@ class LlEmitter {
|
|
|
8483
8591
|
// A dyn JOIN (the C helper's `surface` dyn arm): declared hits
|
|
8484
8592
|
// convert through the per-type toDyn walker (borrowed read → fresh
|
|
8485
8593
|
// +1 tree), a dyn-valued overflow hit passes through (+1 from the
|
|
8486
|
-
// map get), and a miss is JS's undefined — the
|
|
8594
|
+
// map get), and a miss is JS's undefined — the dyn singleton.
|
|
8487
8595
|
this.declare(`declare zeroext i1 @scr_str_eq(ptr, ptr)`);
|
|
8488
8596
|
for (const f of overflowOnly ? [] : shape.fields) {
|
|
8489
8597
|
const lit = this.internLiteral(f.name);
|
|
@@ -8561,7 +8669,7 @@ class LlEmitter {
|
|
|
8561
8669
|
B.br(join);
|
|
8562
8670
|
B.startBlock(ln);
|
|
8563
8671
|
}
|
|
8564
|
-
// The miss path: JS's undefined — the
|
|
8672
|
+
// The miss path: JS's undefined — the dyn singleton, retained.
|
|
8565
8673
|
this.declare(`declare ptr @scr_dyn_undefined()`);
|
|
8566
8674
|
this.declare(`declare ptr @scr_dyn_retain_v(ptr)`);
|
|
8567
8675
|
const u = B.tmp();
|
|
@@ -10559,11 +10667,12 @@ class LlEmitter {
|
|
|
10559
10667
|
if (MAY_THROW_LIB_FNS.has(e.fn) && LIB_FN_SYMS[e.fn] === undefined) {
|
|
10560
10668
|
throw new LlvmUnsupportedError(`libCall:${e.fn}`, e.loc);
|
|
10561
10669
|
}
|
|
10562
|
-
if (e.fn === "math.floor") {
|
|
10670
|
+
if (e.fn === "math.floor" || e.fn === "math.trunc" || e.fn === "math.ceil") {
|
|
10671
|
+
const intr = e.fn === "math.floor" ? "floor" : e.fn === "math.trunc" ? "trunc" : "ceil";
|
|
10563
10672
|
const v = this.emitExpr(e.args[0]);
|
|
10564
|
-
this.declare(`declare double @llvm.
|
|
10673
|
+
this.declare(`declare double @llvm.${intr}.f64(double)`);
|
|
10565
10674
|
const t = B.tmp();
|
|
10566
|
-
B.line(`${t} = call double @llvm.
|
|
10675
|
+
B.line(`${t} = call double @llvm.${intr}.f64(double ${v.name})`);
|
|
10567
10676
|
return { name: t, type: e.type };
|
|
10568
10677
|
}
|
|
10569
10678
|
if (e.fn === "math.abs") {
|