@scriptc/compiler 0.0.9 → 0.0.11
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 +54 -9
- package/dist/backend/emission/emit-exprs.js +170 -14
- package/dist/backend/emission/emit-exprs.js.map +1 -1
- package/dist/backend/emission/emit-walkers.js +29 -2
- package/dist/backend/emission/emit-walkers.js.map +1 -1
- package/dist/backend/emission/emitter.js +25 -1
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/llvm/dyn.d.ts +1 -0
- package/dist/backend/llvm/dyn.js +83 -1
- package/dist/backend/llvm/dyn.js.map +1 -1
- package/dist/backend/llvm/emitter.js +210 -13
- package/dist/backend/llvm/emitter.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 +41 -14
- package/dist/diagnostics/diagnostic.js +79 -27
- package/dist/diagnostics/diagnostic.js.map +1 -1
- package/dist/diagnostics/render.js +8 -0
- package/dist/diagnostics/render.js.map +1 -1
- package/dist/frontend/lowering/lib-boundary.js +11 -1
- package/dist/frontend/lowering/lib-boundary.js.map +1 -1
- package/dist/frontend/lowering/lower-builtins.d.ts +69 -0
- package/dist/frontend/lowering/lower-builtins.js +380 -4
- package/dist/frontend/lowering/lower-builtins.js.map +1 -1
- package/dist/frontend/lowering/lower-calls.d.ts +41 -0
- package/dist/frontend/lowering/lower-calls.js +559 -11
- 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 +51 -1
- package/dist/frontend/lowering/lower-classes.js.map +1 -1
- package/dist/frontend/lowering/lower-containers.d.ts +21 -0
- package/dist/frontend/lowering/lower-containers.js +262 -17
- package/dist/frontend/lowering/lower-containers.js.map +1 -1
- package/dist/frontend/lowering/lower-dgram.js +92 -17
- package/dist/frontend/lowering/lower-dgram.js.map +1 -1
- package/dist/frontend/lowering/lower-emitter.d.ts +70 -3
- package/dist/frontend/lowering/lower-emitter.js +436 -29
- package/dist/frontend/lowering/lower-emitter.js.map +1 -1
- package/dist/frontend/lowering/lower-exprs.d.ts +80 -5
- package/dist/frontend/lowering/lower-exprs.js +651 -23
- package/dist/frontend/lowering/lower-exprs.js.map +1 -1
- package/dist/frontend/lowering/lower-modules.d.ts +8 -5
- package/dist/frontend/lowering/lower-modules.js +144 -19
- package/dist/frontend/lowering/lower-modules.js.map +1 -1
- package/dist/frontend/lowering/lower-namespaces.d.ts +39 -11
- package/dist/frontend/lowering/lower-namespaces.js +166 -24
- package/dist/frontend/lowering/lower-namespaces.js.map +1 -1
- package/dist/frontend/lowering/lower-server.js +211 -4
- package/dist/frontend/lowering/lower-server.js.map +1 -1
- package/dist/frontend/lowering/lower-stmts.d.ts +1 -5
- package/dist/frontend/lowering/lower-stmts.js +293 -10
- package/dist/frontend/lowering/lower-stmts.js.map +1 -1
- package/dist/frontend/lowering/lower-stream.js +178 -10
- package/dist/frontend/lowering/lower-stream.js.map +1 -1
- package/dist/frontend/lowering/lowerer.d.ts +53 -1
- package/dist/frontend/lowering/lowerer.js +210 -19
- package/dist/frontend/lowering/lowerer.js.map +1 -1
- package/dist/frontend/lowering/surfaces.d.ts +44 -0
- package/dist/frontend/lowering/surfaces.js +234 -3
- 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 +144 -135
- package/dist/frontend/program.js.map +1 -1
- package/dist/frontend/shared.d.ts +1 -1
- package/dist/frontend/shared.js +1 -1
- package/dist/frontend/shared.js.map +1 -1
- package/dist/frontend/types.d.ts +13 -0
- package/dist/frontend/types.js +84 -7
- package/dist/frontend/types.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +157 -12
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +163 -13
- package/dist/ir/nodes.js +65 -6
- package/dist/ir/nodes.js.map +1 -1
- package/dist/ir/validate.js +64 -5
- package/dist/ir/validate.js.map +1 -1
- package/dist/library/fence-eval.d.ts +77 -0
- package/dist/library/fence-eval.js +395 -0
- package/dist/library/fence-eval.js.map +1 -0
- package/dist/library/int-infer.d.ts +119 -0
- package/dist/library/int-infer.js +1301 -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 +43 -6
- package/dist/library/profile.js +179 -31
- package/dist/library/profile.js.map +1 -1
- package/dist/library/sidecar.d.ts +23 -0
- package/dist/library/sidecar.js +150 -16
- package/dist/library/sidecar.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +208 -10
|
@@ -197,6 +197,11 @@ const LIB_FN_SYMS = {
|
|
|
197
197
|
"bytes.compareChk": "scr_bytes_compare_chk",
|
|
198
198
|
"buffer.newStringFail": "scr_buffer_new_string_fail",
|
|
199
199
|
"fs.toUnixTimestamp": "scr_fs_to_unix_timestamp",
|
|
200
|
+
"fs.existsChk": "scr_fs_exists_async",
|
|
201
|
+
"fs.mkdtempSyncChk": "scr_fs_mkdtemp_sync_chk",
|
|
202
|
+
"net.connectAttempt": "scr_net_connect_attempt",
|
|
203
|
+
"fs.lchmodSyncChk": "scr_fs_lchmod_sync_chk",
|
|
204
|
+
"fsp.lchmodChk": "scr_fsp_lchmod_chk",
|
|
200
205
|
"fs.readFileSyncBuf": "scr_fs_read_file_bytes",
|
|
201
206
|
"fs.readFileSyncBytes": "scr_fs_read_file_bytes",
|
|
202
207
|
"fs.writeFileSyncBytes": "scr_fs_write_file_bytes",
|
|
@@ -342,9 +347,10 @@ const LIB_FN_SYMS = {
|
|
|
342
347
|
// ambient-this read never throw. The fs dyn read is the sync-fs story.
|
|
343
348
|
"json.parse": "scr_json_parse",
|
|
344
349
|
"dyn.keySet": "scr_dyn_key_set",
|
|
350
|
+
"dyn.iterPack": "scr_dyn_iter_pack",
|
|
345
351
|
"dyn.defineProps": "scr_dyn_define_props",
|
|
346
352
|
"dyn.typeof": "scr_dyn_typeof",
|
|
347
|
-
"dyn.toString": "
|
|
353
|
+
"dyn.toString": "scr_dyn_to_string_method",
|
|
348
354
|
"dyn.this": "scr_dyn_this_get",
|
|
349
355
|
"insp.dyn": "scr_insp_dyn",
|
|
350
356
|
"insp.dynS": "scr_insp_dyn_s",
|
|
@@ -397,6 +403,8 @@ const LIB_FN_SYMS = {
|
|
|
397
403
|
// generic pending check; loop liveness rides USES_TIMERS_LIB_FNS.
|
|
398
404
|
"readable.push": "scr_stream_push",
|
|
399
405
|
"readable.pushStr": "scr_stream_push_str",
|
|
406
|
+
"readable.pushStrEnc": "scr_stream_push_str_enc",
|
|
407
|
+
"readable.pushEncoding": "scr_stream_set_push_encoding",
|
|
400
408
|
"readable.pushNull": "scr_stream_push_null",
|
|
401
409
|
"readable.pushDyn": "scr_stream_push_dyn",
|
|
402
410
|
"readable.unshift": "scr_stream_unshift",
|
|
@@ -498,6 +506,11 @@ const LIB_FN_SYMS = {
|
|
|
498
506
|
// stream/promises' finished form (+1 promise; may-throw pending check;
|
|
499
507
|
// the pipeline form needs the stream-array compound and emits below).
|
|
500
508
|
"sp.finished": "scr_sp_finished",
|
|
509
|
+
// stream/consumers' promise consumers (+1 promises; may-throw pending
|
|
510
|
+
// check — the 'newListener' meta emit can run user code).
|
|
511
|
+
"sc.text": "scr_sc_text",
|
|
512
|
+
"sc.json": "scr_sc_json",
|
|
513
|
+
"sc.buffer": "scr_sc_buffer",
|
|
501
514
|
"dc.channel": "scr_dc_channel",
|
|
502
515
|
"dc.subscribe": "scr_dc_subscribe",
|
|
503
516
|
"dc.unsubscribe": "scr_dc_unsubscribe",
|
|
@@ -559,6 +572,14 @@ const LIB_FN_SYMS = {
|
|
|
559
572
|
"dyn.objKeys": "scr_dyn_obj_keys",
|
|
560
573
|
"dyn.hasOwn": "scr_dyn_has_own",
|
|
561
574
|
"dyn.assign": "scr_dyn_assign",
|
|
575
|
+
// variadic Object.assign: the source pack (push never throws; the
|
|
576
|
+
// spread flatten throws V8's spread-call TypeErrors) and the final
|
|
577
|
+
// left-to-right copy (ToObject TypeError on a nullish target).
|
|
578
|
+
"dyn.packPush": "scr_dyn_pack_push",
|
|
579
|
+
"dyn.packPushSpread": "scr_dyn_pack_push_spread",
|
|
580
|
+
"dyn.packPushSpreadIter": "scr_dyn_pack_push_spread_iter",
|
|
581
|
+
"dyn.assignAll": "scr_dyn_assign_all",
|
|
582
|
+
"dyn.objCreateNullProto": "scr_dyn_new_obj_null_proto",
|
|
562
583
|
"dyn.objValues": "scr_dyn_obj_values",
|
|
563
584
|
"dyn.objEntries": "scr_dyn_obj_entries",
|
|
564
585
|
"dyn.structuredClone": "scr_structured_clone",
|
|
@@ -590,7 +611,8 @@ const USES_TIMERS_LIB_FNS = new Set([
|
|
|
590
611
|
"readable.init", "writable.init", "duplex.init", "transform.init", "passthrough.init",
|
|
591
612
|
"readable.newDyn", "writable.newDyn", "duplex.newDyn", "transform.newDyn", "passthrough.newDyn",
|
|
592
613
|
"readable.initDyn", "writable.initDyn", "duplex.initDyn", "transform.initDyn", "passthrough.initDyn",
|
|
593
|
-
"readable.push", "readable.pushStr", "readable.
|
|
614
|
+
"readable.push", "readable.pushStr", "readable.pushStrEnc", "readable.pushEncoding",
|
|
615
|
+
"readable.pushNull", "readable.pushU", "readable.pushDyn",
|
|
594
616
|
"readable.unshift", "readable.unshiftStr", "readable.read", "readable.setEncoding",
|
|
595
617
|
"readable.nextChunk", "readable.nextChunkDyn", "readable.fromArr", "readable.resume",
|
|
596
618
|
"readable.pipe", "readable.unpipe",
|
|
@@ -602,8 +624,10 @@ const USES_TIMERS_LIB_FNS = new Set([
|
|
|
602
624
|
"process.activeResources",
|
|
603
625
|
"stream.finished", "stream.finishedDyn", "stream.pipeline", "stream.pipelineDyn",
|
|
604
626
|
"sp.finished", "sp.pipeline",
|
|
627
|
+
"sc.text", "sc.json", "sc.buffer",
|
|
605
628
|
"net.listen", "net.listenCb", "net.listenOpts", "net.listenOptsCb",
|
|
606
|
-
"net.connect", "net.connectCb", "net.connectLookup",
|
|
629
|
+
"net.connect", "net.connectCb", "net.connectLookup", "net.connectAttempt",
|
|
630
|
+
"fs.existsChk",
|
|
607
631
|
"http.createServer", "http.createServerEmpty",
|
|
608
632
|
"http.request", "http.requestCb", "http.requestUrl", "http.requestUrlCb",
|
|
609
633
|
"http.requestConn", "http.requestConnCb",
|
|
@@ -1055,6 +1079,12 @@ class LlEmitter {
|
|
|
1055
1079
|
if (this.mod.lib.exports.some((e) => e.params.includes("bytes"))) {
|
|
1056
1080
|
this.declare(`declare ptr @scr_library_bytes_in(ptr, i64, ptr)`);
|
|
1057
1081
|
}
|
|
1082
|
+
if (this.mod.lib.exports.some((e) => e.params.includes("i64"))) {
|
|
1083
|
+
this.declare(`declare double @scr_library_i64_in(i64, ptr)`);
|
|
1084
|
+
}
|
|
1085
|
+
if (this.mod.lib.exports.some((e) => e.params.includes("u64"))) {
|
|
1086
|
+
this.declare(`declare double @scr_library_u64_in(i64, ptr)`);
|
|
1087
|
+
}
|
|
1058
1088
|
if (this.mod.lib.exports.some((e) => e.returns === "string")) {
|
|
1059
1089
|
this.declare(`declare void @scr_library_str_out(ptr, ptr, ptr)`);
|
|
1060
1090
|
}
|
|
@@ -1363,6 +1393,14 @@ class LlEmitter {
|
|
|
1363
1393
|
const trapBytes = Buffer.byteLength(e.inboundBytesTrap, "utf8");
|
|
1364
1394
|
out.push(`@sc_lib_bytes_trap_${e.symbol} = internal constant [${trapBytes + 1} x i8] c"${llStrBytes(e.inboundBytesTrap)}"`, ``);
|
|
1365
1395
|
}
|
|
1396
|
+
if (e.inboundIntTrap !== undefined) {
|
|
1397
|
+
// The i64/u64-in helpers' host-contract trap message (ask 4): an
|
|
1398
|
+
// inbound integer past ±(2^53−1) cannot ride f64 exactly. Same
|
|
1399
|
+
// assembled structured form, same SC4012 code, same
|
|
1400
|
+
// emission-invariance argument as the bytes trap.
|
|
1401
|
+
const trapBytes = Buffer.byteLength(e.inboundIntTrap, "utf8");
|
|
1402
|
+
out.push(`@sc_lib_int_trap_${e.symbol} = internal constant [${trapBytes + 1} x i8] c"${llStrBytes(e.inboundIntTrap)}"`, ``);
|
|
1403
|
+
}
|
|
1366
1404
|
e.params.forEach((cls, i) => {
|
|
1367
1405
|
switch (cls) {
|
|
1368
1406
|
case "f64":
|
|
@@ -1389,6 +1427,19 @@ class LlEmitter {
|
|
|
1389
1427
|
body.push(` %c${i} = sitofp i32 %a${i} to double`);
|
|
1390
1428
|
args.push(`double %c${i}`);
|
|
1391
1429
|
break;
|
|
1430
|
+
case "i64":
|
|
1431
|
+
// Inbound declared-integer edge (ask 4): the helper converts
|
|
1432
|
+
// exactly or delivers the host-contract trap (past ±(2^53−1)
|
|
1433
|
+
// the value cannot ride f64 without silent rounding).
|
|
1434
|
+
params.push(`i64 %a${i}`);
|
|
1435
|
+
body.push(` %c${i} = call double @scr_library_i64_in(i64 %a${i}, ptr @sc_lib_int_trap_${e.symbol})`);
|
|
1436
|
+
args.push(`double %c${i}`);
|
|
1437
|
+
break;
|
|
1438
|
+
case "u64":
|
|
1439
|
+
params.push(`i64 %a${i}`);
|
|
1440
|
+
body.push(` %c${i} = call double @scr_library_u64_in(i64 %a${i}, ptr @sc_lib_int_trap_${e.symbol})`);
|
|
1441
|
+
args.push(`double %c${i}`);
|
|
1442
|
+
break;
|
|
1392
1443
|
case "string":
|
|
1393
1444
|
params.push(`ptr %a${i}_ptr`, `i64 %a${i}_len`);
|
|
1394
1445
|
body.push(` %c${i} = call ptr @scr_library_str_in(ptr %a${i}_ptr, i64 %a${i}_len)`);
|
|
@@ -1415,6 +1466,16 @@ class LlEmitter {
|
|
|
1415
1466
|
retType = "double";
|
|
1416
1467
|
body.push(` %r = call double ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` ret double %r`);
|
|
1417
1468
|
break;
|
|
1469
|
+
case "i64":
|
|
1470
|
+
case "u64":
|
|
1471
|
+
// The outbound declared-integer edge (ask 4): every value
|
|
1472
|
+
// reaching this return was PROVEN whole and inside the class's
|
|
1473
|
+
// range at compile time, so the fp-to-int conversion is exact
|
|
1474
|
+
// by construction — the crossing carries the mathematically
|
|
1475
|
+
// exact integer the f64 held.
|
|
1476
|
+
retType = "i64";
|
|
1477
|
+
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`);
|
|
1478
|
+
break;
|
|
1418
1479
|
case "bool":
|
|
1419
1480
|
retType = "i8";
|
|
1420
1481
|
body.push(` %r = call i1 ${target}(${callArgs})`, ` call void @scr_library_check_exc()`, ` %z = zext i1 %r to i8`, ` ret i8 %z`);
|
|
@@ -4178,6 +4239,33 @@ class LlEmitter {
|
|
|
4178
4239
|
B.line(`${t} = load ptr, ptr ${slot}`);
|
|
4179
4240
|
return this.own({ name: t, type: e.type });
|
|
4180
4241
|
}
|
|
4242
|
+
if (e.left.type.kind === "dyn") {
|
|
4243
|
+
// The checked-dynamic form: the runtime kind decides (UNDEF/
|
|
4244
|
+
// NULL take the default; a wrapped island value asks the
|
|
4245
|
+
// engine); the right runs lazily in its branch (already dyn).
|
|
4246
|
+
const l = this.emitExpr(e.left);
|
|
4247
|
+
this.moveTemp(l);
|
|
4248
|
+
this.declare(`declare zeroext i1 @scr_dyn_is_nullish(ptr)`);
|
|
4249
|
+
const slot = B.slot();
|
|
4250
|
+
B.entryAllocas.push(`${slot} = alloca ptr`);
|
|
4251
|
+
const isN = B.tmp();
|
|
4252
|
+
B.line(`${isN} = call zeroext i1 @scr_dyn_is_nullish(ptr ${l.name})`);
|
|
4253
|
+
const lu = B.newLabel("nuld.u");
|
|
4254
|
+
const lv = B.newLabel("nuld.v");
|
|
4255
|
+
const lj = B.newLabel("nuld.j");
|
|
4256
|
+
B.condBr(isN, lu, lv);
|
|
4257
|
+
B.startBlock(lu);
|
|
4258
|
+
this.releaseValue(l.name, e.left.type);
|
|
4259
|
+
this.emitBranchInto(slot, e.right);
|
|
4260
|
+
B.br(lj);
|
|
4261
|
+
B.startBlock(lv);
|
|
4262
|
+
B.line(`store ptr ${l.name}, ptr ${slot}`);
|
|
4263
|
+
B.br(lj);
|
|
4264
|
+
B.startBlock(lj);
|
|
4265
|
+
const t = B.tmp();
|
|
4266
|
+
B.line(`${t} = load ptr, ptr ${slot}`);
|
|
4267
|
+
return this.own({ name: t, type: e.type });
|
|
4268
|
+
}
|
|
4181
4269
|
if (e.left.type.kind !== "union")
|
|
4182
4270
|
throw new Error("llvm emitter bug: nullish left is not a union");
|
|
4183
4271
|
const def = this.unionsById.get(e.left.type.unionId);
|
|
@@ -5500,6 +5588,16 @@ class LlEmitter {
|
|
|
5500
5588
|
B.line(`${t} = call ptr @${conv}(${valTy} ${v.name})`);
|
|
5501
5589
|
return this.own({ name: t, type: e.type });
|
|
5502
5590
|
}
|
|
5591
|
+
case "dynFromJsval": {
|
|
5592
|
+
// Island value → DOM: the by-reference wrap (scr_dyn_from_jsval
|
|
5593
|
+
// retains the cell in; engine scalars normalize to native DOM
|
|
5594
|
+
// kinds at wrap time). Operand borrowed, result +1, never throws.
|
|
5595
|
+
const v = this.emitExpr(e.value);
|
|
5596
|
+
this.declare(`declare ptr @scr_dyn_from_jsval(ptr)`);
|
|
5597
|
+
const t = B.tmp();
|
|
5598
|
+
B.line(`${t} = call ptr @scr_dyn_from_jsval(ptr ${v.name})`);
|
|
5599
|
+
return this.own({ name: t, type: e.type });
|
|
5600
|
+
}
|
|
5503
5601
|
case "caughtToDyn": {
|
|
5504
5602
|
// A catch binding flowing into an `unknown` slot: the snapshot's
|
|
5505
5603
|
// runtime kind converts through the interned helper (+1 fresh
|
|
@@ -5681,7 +5779,8 @@ class LlEmitter {
|
|
|
5681
5779
|
B.startBlock(lNotObj);
|
|
5682
5780
|
const isArr = B.tmp();
|
|
5683
5781
|
B.line(`${isArr} = icmp eq i32 ${kd}, ${DK.ARR}`);
|
|
5684
|
-
B.
|
|
5782
|
+
const lNotArr = B.newLabel("dhk.na");
|
|
5783
|
+
B.condBr(isArr, lArr, lNotArr);
|
|
5685
5784
|
B.startBlock(lArr);
|
|
5686
5785
|
if (e.key === "length") {
|
|
5687
5786
|
B.line(`store i1 true, ptr ${slot}`);
|
|
@@ -5696,9 +5795,20 @@ class LlEmitter {
|
|
|
5696
5795
|
B.line(`store i1 ${inR}, ptr ${slot}`);
|
|
5697
5796
|
}
|
|
5698
5797
|
B.br(lj);
|
|
5798
|
+
// An ISLAND-held receiver fences loudly (Node asks the real
|
|
5799
|
+
// engine object — `false` would be a silent wrong answer); the
|
|
5800
|
+
// helper answers false for every other kind, so this arm is a
|
|
5801
|
+
// plain unconditional call.
|
|
5802
|
+
B.startBlock(lNotArr);
|
|
5803
|
+
this.declare(`declare zeroext i1 @scr_dyn_isl_fence(ptr, ptr)`);
|
|
5804
|
+
const fenced = B.tmp();
|
|
5805
|
+
B.line(`${fenced} = call zeroext i1 @scr_dyn_isl_fence(ptr ${d.name}, ptr ${this.cstr("'in'")})`);
|
|
5806
|
+
B.line(`store i1 ${fenced}, ptr ${slot}`);
|
|
5807
|
+
B.br(lj);
|
|
5699
5808
|
B.startBlock(lj);
|
|
5700
5809
|
const raw = B.tmp();
|
|
5701
5810
|
B.line(`${raw} = load i1, ptr ${slot}`);
|
|
5811
|
+
this.emitPendingCheck();
|
|
5702
5812
|
if (!e.negated)
|
|
5703
5813
|
return { name: raw, type: e.type };
|
|
5704
5814
|
const neg = B.tmp();
|
|
@@ -5778,13 +5888,18 @@ class LlEmitter {
|
|
|
5778
5888
|
}
|
|
5779
5889
|
else if (e.test === "error") {
|
|
5780
5890
|
// `u instanceof Error`: the DOM's error encoding — an object
|
|
5781
|
-
// carrying the reserved "%error" marker key
|
|
5891
|
+
// carrying the reserved "%error" marker key — or a real engine
|
|
5892
|
+
// Error held by reference (the isl helper answers false for
|
|
5893
|
+
// every non-JSVAL kind, so the call is unconditional).
|
|
5782
5894
|
const kd = this.dynKind(d.name);
|
|
5783
5895
|
const isObj = B.tmp();
|
|
5784
5896
|
B.line(`${isObj} = icmp eq i32 ${kd}, ${DK.OBJ}`);
|
|
5785
5897
|
const slot = B.slot();
|
|
5786
5898
|
B.entryAllocas.push(`${slot} = alloca i1`);
|
|
5787
|
-
|
|
5899
|
+
this.declare(`declare zeroext i1 @scr_dyn_isl_is_error(ptr)`);
|
|
5900
|
+
const isl = B.tmp();
|
|
5901
|
+
B.line(`${isl} = call zeroext i1 @scr_dyn_isl_is_error(ptr ${d.name})`);
|
|
5902
|
+
B.line(`store i1 ${isl}, ptr ${slot}`);
|
|
5788
5903
|
const lObj = B.newLabel("dts.o");
|
|
5789
5904
|
const lj = B.newLabel("dts.j");
|
|
5790
5905
|
B.condBr(isObj, lObj, lj);
|
|
@@ -5818,13 +5933,33 @@ class LlEmitter {
|
|
|
5818
5933
|
}
|
|
5819
5934
|
return acc;
|
|
5820
5935
|
};
|
|
5936
|
+
// ISLAND-held nodes route the tests that depend on the engine's
|
|
5937
|
+
// answer through the scr_dyn_isl_* helpers (false on every
|
|
5938
|
+
// other kind — the calls stay unconditional and branch-free).
|
|
5939
|
+
const orIsl = (acc, helper, arg) => {
|
|
5940
|
+
this.declare(`declare zeroext i1 @${helper}(ptr${arg !== undefined ? ", ptr" : ""})`);
|
|
5941
|
+
const c = B.tmp();
|
|
5942
|
+
B.line(`${c} = call zeroext i1 @${helper}(ptr ${d.name}${arg !== undefined ? `, ptr ${arg}` : ""})`);
|
|
5943
|
+
const o = B.tmp();
|
|
5944
|
+
B.line(`${o} = or i1 ${acc}, ${c}`);
|
|
5945
|
+
return o;
|
|
5946
|
+
};
|
|
5821
5947
|
if (e.test === "nullish") {
|
|
5822
5948
|
test = oneOf([DK.UNDEF, DK.NULL]);
|
|
5823
5949
|
}
|
|
5824
5950
|
else if (e.test === "object") {
|
|
5825
5951
|
// `typeof v === "object"`: objects, arrays, bytes, native
|
|
5826
|
-
// handles, promises, AND null
|
|
5827
|
-
|
|
5952
|
+
// handles, promises, AND null — engine-held objects by the
|
|
5953
|
+
// engine's own typeof.
|
|
5954
|
+
test = orIsl(oneOf([DK.OBJ, DK.ARR, DK.BYTES, DK.HANDLE, DK.PROMISE, DK.NULL]), "scr_dyn_isl_typeof_is", this.cstr("object"));
|
|
5955
|
+
}
|
|
5956
|
+
else if (e.test === "array") {
|
|
5957
|
+
// Array.isArray: the DOM's array kind, or the engine's own
|
|
5958
|
+
// answer for an engine-held value.
|
|
5959
|
+
test = orIsl(oneOf([DK.ARR]), "scr_dyn_isl_is_array");
|
|
5960
|
+
}
|
|
5961
|
+
else if (e.test === "function") {
|
|
5962
|
+
test = orIsl(oneOf([DK.FUNC]), "scr_dyn_isl_typeof_is", this.cstr("function"));
|
|
5828
5963
|
}
|
|
5829
5964
|
else {
|
|
5830
5965
|
const kindOf = {
|
|
@@ -5834,8 +5969,6 @@ class LlEmitter {
|
|
|
5834
5969
|
undefined: DK.UNDEF,
|
|
5835
5970
|
null: DK.NULL,
|
|
5836
5971
|
bytes: DK.BYTES,
|
|
5837
|
-
array: DK.ARR,
|
|
5838
|
-
function: DK.FUNC,
|
|
5839
5972
|
};
|
|
5840
5973
|
test = oneOf([kindOf[e.test]]);
|
|
5841
5974
|
}
|
|
@@ -5947,6 +6080,13 @@ class LlEmitter {
|
|
|
5947
6080
|
return simple("scr_jsval_from_bool", "i1", false);
|
|
5948
6081
|
case "string":
|
|
5949
6082
|
return simple("scr_jsval_from_str", "ptr", false);
|
|
6083
|
+
case "dyn":
|
|
6084
|
+
// A CHECKED-DYNAMIC (DOM) value entering the island: deep copy,
|
|
6085
|
+
// data kinds only — boxed functions/handles/promises throw the
|
|
6086
|
+
// catchable TypeError in the runtime, and a wrapped island value
|
|
6087
|
+
// unwraps to the SAME engine value (the identity round trip).
|
|
6088
|
+
// The C emitter's rule, mirrored.
|
|
6089
|
+
return simple("scr_jsval_from_dyn", "ptr", true);
|
|
5950
6090
|
case "bytes":
|
|
5951
6091
|
// A typed array crossing IN: a COPY (the boundary's copy stance).
|
|
5952
6092
|
return simple("scr_jsval_from_bytes", "ptr", true);
|
|
@@ -8161,6 +8301,10 @@ class LlEmitter {
|
|
|
8161
8301
|
return call("scr_bytes_get", "double (ptr, double)", `ptr ${r.name}, double ${args[0].name}`, false, false);
|
|
8162
8302
|
case "slice":
|
|
8163
8303
|
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);
|
|
8304
|
+
case "subarray":
|
|
8305
|
+
// A +1 VIEW aliasing the receiver's storage (subarray / Buffer's
|
|
8306
|
+
// slice); same index defaults as slice.
|
|
8307
|
+
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);
|
|
8164
8308
|
case "setFrom":
|
|
8165
8309
|
// dst.set(src, offset?) — void; throws Node's RangeError on
|
|
8166
8310
|
// overflow.
|
|
@@ -8214,6 +8358,10 @@ class LlEmitter {
|
|
|
8214
8358
|
B.line(`${t} = fcmp one double ${idx.name}, ${f64Lit(-1)}`);
|
|
8215
8359
|
return { name: t, type: e.type };
|
|
8216
8360
|
}
|
|
8361
|
+
case "fillElem":
|
|
8362
|
+
// Per-element TypedArray fill (non-u8): slice-style index
|
|
8363
|
+
// defaults, never throws; the receiver comes back +1.
|
|
8364
|
+
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);
|
|
8217
8365
|
case "fill":
|
|
8218
8366
|
case "fillNum": {
|
|
8219
8367
|
const sym = method === "fill" ? "scr_bytes_fill" : "scr_bytes_fill_num";
|
|
@@ -8666,6 +8814,54 @@ class LlEmitter {
|
|
|
8666
8814
|
this.emitPendingCheck();
|
|
8667
8815
|
return out;
|
|
8668
8816
|
}
|
|
8817
|
+
if (e.fn === "error.propTypeThrow") {
|
|
8818
|
+
// The property flavor of argTypeThrow — same always-throw shape.
|
|
8819
|
+
const an = this.emitExpr(e.args[0]);
|
|
8820
|
+
const ex = this.emitExpr(e.args[1]);
|
|
8821
|
+
const got = this.emitExpr(e.args[2]);
|
|
8822
|
+
this.declare(`declare void @scr_throw_prop_type(ptr, ptr, ptr)`);
|
|
8823
|
+
B.line(`call void @scr_throw_prop_type(ptr ${an.name}, ptr ${ex.name}, ptr ${got.name})`);
|
|
8824
|
+
const ty = this.llType(e.type);
|
|
8825
|
+
if (ty === "void") {
|
|
8826
|
+
this.emitPendingCheck();
|
|
8827
|
+
return { name: "", type: e.type };
|
|
8828
|
+
}
|
|
8829
|
+
const dummy = ty === "double" ? f64Lit(0) : ty === "i1" ? "false" : "null";
|
|
8830
|
+
const out = this.own({ name: dummy, type: e.type });
|
|
8831
|
+
this.emitPendingCheck();
|
|
8832
|
+
return out;
|
|
8833
|
+
}
|
|
8834
|
+
{
|
|
8835
|
+
// The fs validation-ladder Chk forms that ALWAYS throw (a
|
|
8836
|
+
// validation error or the trailing compiler-rendered fence): every
|
|
8837
|
+
// argument is a ptr (dyns + the fence string), and the typed dummy
|
|
8838
|
+
// is abandoned by the pending check's unwind.
|
|
8839
|
+
const FS_CHK_THROW_SYMS = {
|
|
8840
|
+
"fs.mkdtempChk": "scr_fs_mkdtemp_chk",
|
|
8841
|
+
"fs.readFileChk": "scr_fs_read_file_chk",
|
|
8842
|
+
"fs.opendirChk": "scr_fs_opendir_chk",
|
|
8843
|
+
"fs.watchFileChk": "scr_fs_watch_file_chk",
|
|
8844
|
+
"fs.lchmodChk": "scr_fs_lchmod_chk",
|
|
8845
|
+
"fs.readChk": "scr_fs_read_chk",
|
|
8846
|
+
"fs.streamOptsChk": "scr_fs_stream_opts_chk",
|
|
8847
|
+
"net.connectOptsChk": "scr_net_connect_opts_chk",
|
|
8848
|
+
};
|
|
8849
|
+
const sym = FS_CHK_THROW_SYMS[e.fn];
|
|
8850
|
+
if (sym !== undefined) {
|
|
8851
|
+
const args = e.args.map((a) => this.emitExpr(a));
|
|
8852
|
+
this.declare(`declare void @${sym}(${args.map(() => "ptr").join(", ")})`);
|
|
8853
|
+
B.line(`call void @${sym}(${args.map((a) => `ptr ${a.name}`).join(", ")})`);
|
|
8854
|
+
const ty = this.llType(e.type);
|
|
8855
|
+
if (ty === "void") {
|
|
8856
|
+
this.emitPendingCheck();
|
|
8857
|
+
return { name: "", type: e.type };
|
|
8858
|
+
}
|
|
8859
|
+
const dummy = ty === "double" ? f64Lit(0) : ty === "i1" ? "false" : "null";
|
|
8860
|
+
const out = this.own({ name: dummy, type: e.type });
|
|
8861
|
+
this.emitPendingCheck();
|
|
8862
|
+
return out;
|
|
8863
|
+
}
|
|
8864
|
+
}
|
|
8669
8865
|
if (e.fn === "error.nodeThrow") {
|
|
8670
8866
|
// The compiler-resolved Node-parity throw (always throws — the
|
|
8671
8867
|
// typed dummy is abandoned by the pending check's unwind).
|
|
@@ -10417,11 +10613,12 @@ class LlEmitter {
|
|
|
10417
10613
|
if (MAY_THROW_LIB_FNS.has(e.fn) && LIB_FN_SYMS[e.fn] === undefined) {
|
|
10418
10614
|
throw new LlvmUnsupportedError(`libCall:${e.fn}`, e.loc);
|
|
10419
10615
|
}
|
|
10420
|
-
if (e.fn === "math.floor") {
|
|
10616
|
+
if (e.fn === "math.floor" || e.fn === "math.trunc" || e.fn === "math.ceil") {
|
|
10617
|
+
const intr = e.fn === "math.floor" ? "floor" : e.fn === "math.trunc" ? "trunc" : "ceil";
|
|
10421
10618
|
const v = this.emitExpr(e.args[0]);
|
|
10422
|
-
this.declare(`declare double @llvm.
|
|
10619
|
+
this.declare(`declare double @llvm.${intr}.f64(double)`);
|
|
10423
10620
|
const t = B.tmp();
|
|
10424
|
-
B.line(`${t} = call double @llvm.
|
|
10621
|
+
B.line(`${t} = call double @llvm.${intr}.f64(double ${v.name})`);
|
|
10425
10622
|
return { name: t, type: e.type };
|
|
10426
10623
|
}
|
|
10427
10624
|
if (e.fn === "math.abs") {
|