@scriptc/compiler 0.0.17 → 0.0.18

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.
Files changed (51) hide show
  1. package/ambient/scriptc-node-fallback.d.ts +4 -4
  2. package/dist/backend/cc.d.ts +5 -0
  3. package/dist/backend/cc.js +2 -0
  4. package/dist/backend/cc.js.map +1 -1
  5. package/dist/backend/emission/emit-async.js +35 -2
  6. package/dist/backend/emission/emit-async.js.map +1 -1
  7. package/dist/backend/emission/emit-exprs.js +40 -4
  8. package/dist/backend/emission/emit-exprs.js.map +1 -1
  9. package/dist/backend/emission/emitter.js +69 -11
  10. package/dist/backend/emission/emitter.js.map +1 -1
  11. package/dist/backend/emission/may-throw.d.ts +3 -3
  12. package/dist/backend/emission/may-throw.js +15 -4
  13. package/dist/backend/emission/may-throw.js.map +1 -1
  14. package/dist/backend/llvm/emitter.js +199 -21
  15. package/dist/backend/llvm/emitter.js.map +1 -1
  16. package/dist/frontend/lowering/lower-builtins.js +4 -7
  17. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  18. package/dist/frontend/lowering/lower-calls.js +17 -9
  19. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  20. package/dist/frontend/lowering/lower-containers.d.ts +22 -17
  21. package/dist/frontend/lowering/lower-containers.js +628 -51
  22. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  23. package/dist/frontend/lowering/lower-exprs.js +19 -1
  24. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  25. package/dist/frontend/lowering/lower-island.js +55 -7
  26. package/dist/frontend/lowering/lower-island.js.map +1 -1
  27. package/dist/frontend/lowering/lower-modules.js +144 -10
  28. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  29. package/dist/frontend/lowering/lower-stmts.d.ts +8 -0
  30. package/dist/frontend/lowering/lower-stmts.js +408 -21
  31. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  32. package/dist/frontend/lowering/lowerer.d.ts +38 -0
  33. package/dist/frontend/lowering/lowerer.js +149 -2
  34. package/dist/frontend/lowering/lowerer.js.map +1 -1
  35. package/dist/frontend/lowering/surfaces.js +4 -0
  36. package/dist/frontend/lowering/surfaces.js.map +1 -1
  37. package/dist/index.js +5 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/ir/nodes.d.ts +46 -12
  40. package/dist/ir/nodes.js +41 -0
  41. package/dist/ir/nodes.js.map +1 -1
  42. package/dist/ir/serialize.d.ts +1 -1
  43. package/dist/ir/serialize.js +1 -1
  44. package/dist/ir/validate.js +98 -39
  45. package/dist/ir/validate.js.map +1 -1
  46. package/dist/library/int-infer.js +191 -25
  47. package/dist/library/int-infer.js.map +1 -1
  48. package/dist/library/int-infer.test.js +206 -1
  49. package/dist/library/int-infer.test.js.map +1 -1
  50. package/package.json +2 -2
  51. package/surface-manifest.json +25 -1
@@ -564,7 +564,7 @@ const LIB_FN_SYMS = {
564
564
  "dc.chanRunStores": "scr_dc_chan_run_stores",
565
565
  // process warning/rejection events (scr_lib.c / scr_async_dyn.c):
566
566
  // dyn listeners are borrowed (the runtime retains its copy);
567
- // onUnhandledRejection marks the loop live (the loop-end report
567
+ // onUnhandledRejection marks the loop live (the checkpoint report
568
568
  // dispatches the listeners).
569
569
  "process.onWarning": "scr_process_on_warning",
570
570
  "process.offWarning": "scr_process_off_warning",
@@ -649,12 +649,12 @@ const USES_TIMERS_LIB_FNS = new Set([
649
649
  "fs.existsChk",
650
650
  "http.createServer", "http.createServerEmpty",
651
651
  "http.request", "http.requestCb", "http.requestUrl", "http.requestUrlCb",
652
- "https.requestUrl", "https.requestUrlCb",
652
+ "https.request", "https.requestCb", "https.requestUrl", "https.requestUrlCb",
653
653
  "http.requestConn", "http.requestConnCb",
654
654
  "http.agentNew", "http.requestAgent", "http.requestAgentCb",
655
655
  // The dyn-async slice (emit-exprs.ts's markings): fiber parks, the
656
656
  // microtask/immediate mints, the tracing-promise reaction fiber, and
657
- // the loop-end unhandled-rejection report.
657
+ // the checkpoint unhandled-rejection report.
658
658
  "async.hop", "async.awaitDyn",
659
659
  "dc.tcTracePromise",
660
660
  "process.onUnhandledRejection", "process.onRejectionHandled",
@@ -1068,6 +1068,7 @@ class LlEmitter {
1068
1068
  ];
1069
1069
  };
1070
1070
  const globalReleases = globalReleaseLines("g");
1071
+ const asyncEntry = this.fnByName.get(this.mod.entry)?.async === true;
1071
1072
  const entryMayThrow = this.mayThrow.has(this.mod.entry);
1072
1073
  // The event loop runs when timers appeared OR any async/generator
1073
1074
  // function exists (the C main's hasAsync || hasGenerators ||
@@ -1077,17 +1078,26 @@ class LlEmitter {
1077
1078
  // async loop-exhaustion story.
1078
1079
  const runsLoop = this.usesTimers ||
1079
1080
  this.mod.functions.some((f) => f.async === true || f.generator !== undefined);
1080
- const uncaughtReleases = entryMayThrow ? globalReleaseLines("gu") : [];
1081
+ const uncaughtReleases = entryMayThrow && !asyncEntry ? globalReleaseLines("gu") : [];
1081
1082
  const loopReleasesU = runsLoop ? globalReleaseLines("gl") : [];
1082
1083
  const loopReleasesR = runsLoop ? globalReleaseLines("gr") : [];
1084
+ const topRejectReleases = asyncEntry ? globalReleaseLines("gt") : [];
1085
+ const topPendingReleases = asyncEntry ? globalReleaseLines("gp") : [];
1086
+ const loopReportedReleases = runsLoop ? globalReleaseLines("gq") : [];
1083
1087
  // main's epilogues read the flag / the loop entry points — declared
1084
1088
  // HERE, before the extern block flushes (a pending check usually
1085
1089
  // declared the flag already; the Set dedupes).
1086
1090
  if (entryMayThrow || runsLoop)
1087
1091
  this.declare(`declare zeroext i1 @scr_exc_pending()`);
1088
1092
  if (runsLoop) {
1089
- this.declare(`declare void @scr_loop_run()`);
1093
+ this.declare(`declare zeroext i1 @scr_loop_run(ptr)`);
1090
1094
  this.declare(`declare zeroext i1 @scr_report_unhandled_rejections()`);
1095
+ this.declare(`declare void @scr_discard_unhandled_rejections()`);
1096
+ }
1097
+ if (asyncEntry) {
1098
+ this.declare(`declare i32 @scr_promise_finish_top_level(ptr)`);
1099
+ this.declare(`declare void @scr_promise_rethrow_top_level(ptr)`);
1100
+ this.declare(`declare void @scr_promise_release(ptr)`);
1091
1101
  }
1092
1102
  // LIBRARY mode: the runtime entry points the generated library
1093
1103
  // symbols delegate to — declared before the extern block flushes.
@@ -1288,9 +1298,11 @@ class LlEmitter {
1288
1298
  ...(usesEvents ? [` call void @scr_events_install()`] : []),
1289
1299
  // fs.watch programs fill the loop's watch hooks the same way —
1290
1300
  // scr_watch.c links only when this line is emitted.
1291
- ...(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)`, ` call void @${mangleFunction(this.mod.entry)}()`,
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
1302
+ ? [` %top = call ptr @${mangleAsyncSpawn(this.mod.entry)}()`]
1303
+ : [` call void @${mangleFunction(this.mod.entry)}()`]),
1292
1304
  // Uncaught exception from top-level code: Node exits 1.
1293
- ...(entryMayThrow
1305
+ ...(entryMayThrow && !asyncEntry
1294
1306
  ? [
1295
1307
  ` %exc = call zeroext i1 @scr_exc_pending()`,
1296
1308
  ` br i1 %exc, label %uncaught, label %ok`,
@@ -1307,15 +1319,44 @@ class LlEmitter {
1307
1319
  // both exit 1, like Node — the C main's loop block exactly.
1308
1320
  ...(runsLoop
1309
1321
  ? [
1310
- ` call void @scr_loop_run()`,
1322
+ ` %loop_rejection = call zeroext i1 @scr_loop_run(ptr ${asyncEntry ? "%top" : "null"})`,
1311
1323
  ` %lexc = call zeroext i1 @scr_exc_pending()`,
1312
1324
  ` br i1 %lexc, label %luncaught, label %lok`,
1313
1325
  `luncaught:`,
1314
1326
  ` call void @scr_exc_print_uncaught()`,
1327
+ ...(asyncEntry ? [` call void @scr_promise_release(ptr %top)`] : []),
1315
1328
  ...exitListenerLines("xl"),
1316
1329
  ...loopReleasesU,
1317
1330
  ` ret i32 1`,
1318
1331
  `lok:`,
1332
+ ` br i1 %loop_rejection, label %lreported, label %lclean`,
1333
+ `lreported:`,
1334
+ ` call void @scr_discard_unhandled_rejections()`,
1335
+ ...(asyncEntry ? [` call void @scr_promise_release(ptr %top)`] : []),
1336
+ ...exitListenerLines("xq"),
1337
+ ...loopReportedReleases,
1338
+ ` ret i32 1`,
1339
+ `lclean:`,
1340
+ ...(asyncEntry
1341
+ ? [
1342
+ ` %tla_status = call i32 @scr_promise_finish_top_level(ptr %top)`,
1343
+ ` %tla_rejected = icmp eq i32 %tla_status, 1`,
1344
+ ` br i1 %tla_rejected, label %tla_fail, label %tla_not_rejected`,
1345
+ `tla_fail:`,
1346
+ // The loop already delivered every earlier-checkpoint
1347
+ // rejection. Drop same-checkpoint competitors before
1348
+ // surfacing the fatal module verdict.
1349
+ ` call void @scr_discard_unhandled_rejections()`,
1350
+ ` call void @scr_promise_rethrow_top_level(ptr %top)`,
1351
+ ` call void @scr_promise_release(ptr %top)`,
1352
+ ` call void @scr_exc_print_uncaught()`,
1353
+ ...exitListenerLines("xt"),
1354
+ ...topRejectReleases,
1355
+ ` ret i32 1`,
1356
+ `tla_not_rejected:`,
1357
+ ` call void @scr_promise_release(ptr %top)`,
1358
+ ]
1359
+ : []),
1319
1360
  ` %rej = call zeroext i1 @scr_report_unhandled_rejections()`,
1320
1361
  ` br i1 %rej, label %lrej, label %lrok`,
1321
1362
  `lrej:`,
@@ -1323,6 +1364,17 @@ class LlEmitter {
1323
1364
  ...loopReleasesR,
1324
1365
  ` ret i32 1`,
1325
1366
  `lrok:`,
1367
+ ...(asyncEntry
1368
+ ? [
1369
+ ` %tla_pending = icmp eq i32 %tla_status, 13`,
1370
+ ` br i1 %tla_pending, label %tla_stuck, label %tla_ok`,
1371
+ `tla_stuck:`,
1372
+ ...exitListenerLines("xp"),
1373
+ ...topPendingReleases,
1374
+ ` ret i32 13`,
1375
+ `tla_ok:`,
1376
+ ]
1377
+ : []),
1326
1378
  ]
1327
1379
  : []), ...exitListenerLines("xn"), ...globalReleases, ` ret i32 0`, `}`, ``,
1328
1380
  // sanitize_address is inert under the plain pipeline; the sanitized
@@ -1645,9 +1697,29 @@ class LlEmitter {
1645
1697
  out.push(...tr);
1646
1698
  // Spawn wrapper: pack the args (+1 moves in), spawn the fiber.
1647
1699
  const params = fieldTys.map((ty, i) => `${ty} %a${i}`);
1700
+ const cache = fn.asyncCacheGlobal !== undefined ? mangleGlobal(fn.asyncCacheGlobal) : null;
1701
+ const cycleCache = fn.asyncCycleCacheGlobal !== undefined ? mangleGlobal(fn.asyncCycleCacheGlobal) : null;
1702
+ if (cache !== null || cycleCache !== null) {
1703
+ this.declare(`declare ptr @scr_promise_retain_v(ptr)`);
1704
+ this.declare(`declare void @scr_promise_release(ptr)`);
1705
+ }
1706
+ if (cache !== null) {
1707
+ this.declare(`declare void @scr_promise_mark_handled(ptr)`);
1708
+ }
1648
1709
  const sp = [
1649
1710
  `define internal ptr @${mangleAsyncSpawn(fn.name)}(${params.join(", ")}) ${FN_ATTRS} { ; spawn ${fn.name}`,
1650
1711
  `entry:`,
1712
+ ...(cache !== null
1713
+ ? [
1714
+ ` %cached = load ptr, ptr @${cache}`,
1715
+ ` %cache_hit = icmp ne ptr %cached, null`,
1716
+ ` br i1 %cache_hit, label %cached_return, label %cache_miss`,
1717
+ `cached_return:`,
1718
+ ` %cached_owned = call ptr @scr_promise_retain_v(ptr %cached)`,
1719
+ ` ret ptr %cached_owned`,
1720
+ `cache_miss:`,
1721
+ ]
1722
+ : []),
1651
1723
  ` %ap = call ptr @malloc(i64 ${sizeOf})`,
1652
1724
  ` %isnull = icmp eq ptr %ap, null`,
1653
1725
  ` br i1 %isnull, label %oom, label %ok`,
@@ -1666,7 +1738,36 @@ class LlEmitter {
1666
1738
  const src = lifted && i === 0 ? "%env" : `%a${i}`;
1667
1739
  sp.push(` %sp${i} = getelementptr inbounds %${pack}, ptr %ap, i64 0, i32 ${i}`, ` store ${ty} ${src}, ptr %sp${i}`);
1668
1740
  });
1669
- sp.push(` %p = call ptr @scr_async_spawn(ptr @${mangleTrampoline(fn.name)}, ptr %ap)`, ` ret ptr %p`, `}`, ``);
1741
+ sp.push(` %p = call ptr @scr_async_spawn(ptr @${mangleTrampoline(fn.name)}, ptr %ap)`, ...(cache !== null
1742
+ ? [
1743
+ // The module loader owns this evaluation promise
1744
+ // immediately. A later sibling can throw before the
1745
+ // aggregate dependency wait is built, but this rejection
1746
+ // must never become an unrelated unhandled rejection.
1747
+ ` call void @scr_promise_mark_handled(ptr %p)`,
1748
+ ]
1749
+ : []), ...(cache !== null
1750
+ ? [
1751
+ ` %cache_owned = call ptr @scr_promise_retain_v(ptr %p)`,
1752
+ // The eager spawn may have re-entered this guarded module
1753
+ // through an admitted async cycle and installed a temporary
1754
+ // cache entry. Drop that owned slot before replacing it
1755
+ // with the outer evaluation promise.
1756
+ ` %replaced_cache = load ptr, ptr @${cache}`,
1757
+ ` call void @scr_promise_release(ptr %replaced_cache)`,
1758
+ ` store ptr %cache_owned, ptr @${cache}`,
1759
+ ]
1760
+ : []), ...(cycleCache !== null
1761
+ ? [
1762
+ // Eager recursive spawns publish from the inside out. The
1763
+ // runtime-requested outermost member writes last and is the
1764
+ // SCC's actual evaluation root.
1765
+ ` %cycle_cache_owned = call ptr @scr_promise_retain_v(ptr %p)`,
1766
+ ` %replaced_cycle_cache = load ptr, ptr @${cycleCache}`,
1767
+ ` call void @scr_promise_release(ptr %replaced_cycle_cache)`,
1768
+ ` store ptr %cycle_cache_owned, ptr @${cycleCache}`,
1769
+ ]
1770
+ : []), ` ret ptr %p`, `}`, ``);
1670
1771
  out.push(...sp);
1671
1772
  }
1672
1773
  out.push(...this.emitGenScaffolding());
@@ -3651,11 +3752,12 @@ class LlEmitter {
3651
3752
  case "strCmp": {
3652
3753
  const l = this.emitExpr(e.left);
3653
3754
  const r = this.emitExpr(e.right);
3654
- this.declare(`declare i32 @scr_str_cmp(ptr, ptr)`);
3755
+ const fn = e.utf16 === true ? "scr_str_cmp_u16" : "scr_str_cmp";
3756
+ this.declare(`declare i32 @${fn}(ptr, ptr)`);
3655
3757
  const c = B.tmp();
3656
3758
  const t = B.tmp();
3657
3759
  const pred = { "<": "slt", "<=": "sle", ">": "sgt", ">=": "sge" }[e.op];
3658
- B.line(`${c} = call i32 @scr_str_cmp(ptr ${l.name}, ptr ${r.name})`);
3760
+ B.line(`${c} = call i32 @${fn}(ptr ${l.name}, ptr ${r.name})`);
3659
3761
  B.line(`${t} = icmp ${pred} i32 ${c}, 0`);
3660
3762
  return { name: t, type: e.type };
3661
3763
  }
@@ -5533,6 +5635,15 @@ class LlEmitter {
5533
5635
  case "libCall":
5534
5636
  return this.emitLibCall(e);
5535
5637
  case "intrinsic": {
5638
+ if (e.name === "module.await") {
5639
+ // Internal ESM dependency wait: pending promises park the module
5640
+ // fiber, while settled ones continue synchronously.
5641
+ const p = this.emitExpr(e.args[0]);
5642
+ this.declare(`declare void @scr_module_await(ptr)`);
5643
+ B.line(`call void @scr_module_await(ptr ${p.name})`);
5644
+ this.emitPendingCheck();
5645
+ return { name: "", type: e.type };
5646
+ }
5536
5647
  if (e.name === "promise.all") {
5537
5648
  // The runtime countdown combinator (emit-exprs.ts): a pre-sized
5538
5649
  // values array filled per INPUT index as entries fulfill, plus
@@ -8052,6 +8163,33 @@ class LlEmitter {
8052
8163
  B.line(`${t} = call ptr @scr_arr_slice(ptr ${r.name}, double ${start}, double ${end})`);
8053
8164
  return this.own({ name: t, type: e.type });
8054
8165
  }
8166
+ case "toReversed": {
8167
+ this.declare(`declare ptr @scr_arr_to_reversed(ptr)`);
8168
+ const t = B.tmp();
8169
+ B.line(`${t} = call ptr @scr_arr_to_reversed(ptr ${r.name})`);
8170
+ return this.own({ name: t, type: e.type });
8171
+ }
8172
+ case "toSpliced": {
8173
+ const start = this.emitExpr(e.args[0]);
8174
+ const count = this.emitExpr(e.args[1]);
8175
+ const items = this.emitExpr(e.args[2]);
8176
+ this.declare(`declare ptr @scr_arr_to_spliced(ptr, double, double, ptr)`);
8177
+ const t = B.tmp();
8178
+ B.line(`${t} = call ptr @scr_arr_to_spliced(ptr ${r.name}, double ${start.name}, ` +
8179
+ `double ${count.name}, ptr ${items.name})`);
8180
+ return this.own({ name: t, type: e.type });
8181
+ }
8182
+ case "with": {
8183
+ const index = this.emitExpr(e.args[0]);
8184
+ const value = this.emitExpr(e.args[1]);
8185
+ this.declare(`declare ptr @scr_arr_with_${acc}(ptr, double, ${accArg})`);
8186
+ const t = B.tmp();
8187
+ B.line(`${t} = call ptr @scr_arr_with_${acc}(ptr ${r.name}, double ${index.name}, ` +
8188
+ `${accTy} ${value.name})`);
8189
+ const out = this.own({ name: t, type: e.type });
8190
+ this.emitPendingCheck();
8191
+ return out;
8192
+ }
8055
8193
  case "splice": {
8056
8194
  // The removal splice: removed elements come back as a fresh +1
8057
8195
  // array, ownership MOVED out of the receiver. An omitted count
@@ -8495,6 +8633,14 @@ class LlEmitter {
8495
8633
  // A +1 VIEW aliasing the receiver's storage (subarray / Buffer's
8496
8634
  // slice); same index defaults as slice.
8497
8635
  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);
8636
+ case "toReversed":
8637
+ return call("scr_bytes_to_reversed", "ptr (ptr)", `ptr ${r.name}`, true, false);
8638
+ case "with":
8639
+ return call("scr_bytes_with", "ptr (ptr, double, double)", `ptr ${r.name}, double ${args[0].name}, double ${args[1].name}`, true, true);
8640
+ case "join":
8641
+ return call("scr_bytes_join", "ptr (ptr, ptr)", `ptr ${r.name}, ptr ${args[0].name}`, true, false);
8642
+ case "toArray":
8643
+ return call("scr_bytes_to_arr", "ptr (ptr)", `ptr ${r.name}`, true, false);
8498
8644
  case "setFrom":
8499
8645
  // dst.set(src, offset?) — void; throws Node's RangeError on
8500
8646
  // overflow.
@@ -10736,14 +10882,17 @@ class LlEmitter {
10736
10882
  }
10737
10883
  if (e.fn === "http.request" || e.fn === "http.requestCb" || e.fn === "http.requestUrl" || e.fn === "http.requestUrlCb" ||
10738
10884
  e.fn === "http.requestAgent" || e.fn === "http.requestAgentCb" ||
10885
+ e.fn === "https.request" || e.fn === "https.requestCb" ||
10739
10886
  e.fn === "https.requestUrl" || e.fn === "https.requestUrlCb") {
10740
10887
  // The https URL row is the http one with the TLS entry point — same
10741
- // three arguments, same response-callback adapter. (The https
10742
- // OPTIONS forms are a separate, wider row and are not here yet.)
10888
+ // three arguments, same response-callback adapter. The https options
10889
+ // row is wider: rejectUnauthorized stays an i1, while its ScrStr or
10890
+ // ScrBytes CA value expands to the runtime's raw pointer + length.
10743
10891
  const isTls = e.fn.startsWith("https.");
10744
- const isUrl = isTls || e.fn.startsWith("http.requestUrl");
10892
+ const isUrl = e.fn.includes("requestUrl");
10893
+ const isTlsOptions = isTls && !isUrl;
10745
10894
  const isAgent = e.fn.startsWith("http.requestAgent");
10746
- const cbIdx = isUrl ? 3 : isAgent ? 8 : 7;
10895
+ const cbIdx = isUrl ? 3 : isTlsOptions ? 9 : isAgent ? 8 : 7;
10747
10896
  const hasCb = e.fn.endsWith("Cb");
10748
10897
  const args = e.args.map((a) => this.emitExpr(a));
10749
10898
  let cb = "null";
@@ -10759,13 +10908,42 @@ class LlEmitter {
10759
10908
  adapter = `@${sym}`;
10760
10909
  }
10761
10910
  const head = args.slice(0, cbIdx);
10762
- const decls = head.map((a) => (this.llType(a.type) === "i1" ? "i1 zeroext" : this.llType(a.type)));
10763
- const entry = isTls ? "scr_https_request_url"
10764
- : isUrl ? "scr_http_request_url"
10765
- : isAgent ? "scr_http_request_agent" : "scr_http_request";
10766
- this.declare(`declare ptr @${entry}(${[...decls, "ptr", "ptr"].join(", ")})`);
10911
+ const entry = isTlsOptions ? "scr_https_request"
10912
+ : isTls ? "scr_https_request_url"
10913
+ : isUrl ? "scr_http_request_url"
10914
+ : isAgent ? "scr_http_request_agent" : "scr_http_request";
10915
+ let callArgs = head.map((a) => `${this.llType(a.type)} ${a.name}`);
10916
+ if (isTlsOptions) {
10917
+ const ca = args[8];
10918
+ const caLenPtr = B.tmp();
10919
+ const caLen = B.tmp();
10920
+ let caData;
10921
+ if (ca.type.kind === "string") {
10922
+ caData = B.tmp();
10923
+ B.line(`${caLenPtr} = getelementptr inbounds %ScrStr, ptr ${ca.name}, i64 0, i32 1`);
10924
+ B.line(`${caLen} = load i64, ptr ${caLenPtr}`);
10925
+ B.line(`${caData} = getelementptr inbounds i8, ptr ${ca.name}, i64 24`);
10926
+ }
10927
+ else if (ca.type.kind === "bytes" && ca.type.elem === "u8") {
10928
+ const caDataPtr = B.tmp();
10929
+ caData = B.tmp();
10930
+ B.line(`${caLenPtr} = getelementptr inbounds i8, ptr ${ca.name}, i64 8`);
10931
+ B.line(`${caLen} = load i64, ptr ${caLenPtr}`);
10932
+ B.line(`${caDataPtr} = getelementptr inbounds i8, ptr ${ca.name}, i64 24`);
10933
+ B.line(`${caData} = load ptr, ptr ${caDataPtr}`);
10934
+ }
10935
+ else {
10936
+ throw new Error(`llvm emitter bug: ${e.fn} CA is not a string or Buffer`);
10937
+ }
10938
+ callArgs = [...callArgs.slice(0, 8), `ptr ${caData}`, `i64 ${caLen}`];
10939
+ this.declare(`declare ptr @scr_https_request(ptr, double, ptr, ptr, double, ptr, i1 zeroext, i1 zeroext, ptr, i64, ptr, ptr)`);
10940
+ }
10941
+ else {
10942
+ const decls = head.map((a) => (this.llType(a.type) === "i1" ? "i1 zeroext" : this.llType(a.type)));
10943
+ this.declare(`declare ptr @${entry}(${[...decls, "ptr", "ptr"].join(", ")})`);
10944
+ }
10767
10945
  const t = B.tmp();
10768
- B.line(`${t} = call ptr @${entry}(${[...head.map((a) => `${this.llType(a.type)} ${a.name}`), `ptr ${cb}`, `ptr ${adapter}`].join(", ")})`);
10946
+ B.line(`${t} = call ptr @${entry}(${[...callArgs, `ptr ${cb}`, `ptr ${adapter}`].join(", ")})`);
10769
10947
  const out = this.own({ name: t, type: e.type });
10770
10948
  if (MAY_THROW_LIB_FNS.has(e.fn))
10771
10949
  this.emitPendingCheck();