@scriptc/compiler 0.0.34 → 0.0.35

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 (66) hide show
  1. package/dist/backend/cc-cache.test.js +969 -7
  2. package/dist/backend/cc-cache.test.js.map +1 -1
  3. package/dist/backend/cc.d.ts +90 -18
  4. package/dist/backend/cc.js +953 -276
  5. package/dist/backend/cc.js.map +1 -1
  6. package/dist/backend/llvm/split.d.ts +43 -0
  7. package/dist/backend/llvm/split.js +227 -0
  8. package/dist/backend/llvm/split.js.map +1 -0
  9. package/dist/backend/llvm/split.test.d.ts +1 -0
  10. package/dist/backend/llvm/split.test.js +102 -0
  11. package/dist/backend/llvm/split.test.js.map +1 -0
  12. package/dist/backend/object-localize.test.js +20 -0
  13. package/dist/backend/object-localize.test.js.map +1 -1
  14. package/dist/executable/early-cache.d.ts +86 -0
  15. package/dist/executable/early-cache.js +460 -0
  16. package/dist/executable/early-cache.js.map +1 -0
  17. package/dist/executable/early-cache.test.d.ts +1 -0
  18. package/dist/executable/early-cache.test.js +300 -0
  19. package/dist/executable/early-cache.test.js.map +1 -0
  20. package/dist/ffi/profile.d.ts +7 -2
  21. package/dist/ffi/profile.js +1 -0
  22. package/dist/ffi/profile.js.map +1 -1
  23. package/dist/frontend/lowering/lower-builtins.js +2 -2
  24. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  25. package/dist/frontend/lowering/lower-calls.js +14 -4
  26. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  27. package/dist/frontend/lowering/lower-containers.js +18 -23
  28. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  29. package/dist/frontend/lowering/lower-exprs.js +22 -10
  30. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  31. package/dist/frontend/lowering/lower-island.js +3 -3
  32. package/dist/frontend/lowering/lower-island.js.map +1 -1
  33. package/dist/frontend/lowering/lower-mixins.js +1 -1
  34. package/dist/frontend/lowering/lower-mixins.js.map +1 -1
  35. package/dist/frontend/lowering/lower-stmts.js +1 -1
  36. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  37. package/dist/frontend/lowering/lowerer.d.ts +6 -0
  38. package/dist/frontend/lowering/lowerer.js +230 -81
  39. package/dist/frontend/lowering/lowerer.js.map +1 -1
  40. package/dist/frontend/lowering/surfaces.js +1 -1
  41. package/dist/frontend/lowering/surfaces.js.map +1 -1
  42. package/dist/frontend/program.js +42 -13
  43. package/dist/frontend/program.js.map +1 -1
  44. package/dist/frontend/ts7/checker.d.ts +40 -2
  45. package/dist/frontend/ts7/checker.js +194 -32
  46. package/dist/frontend/ts7/checker.js.map +1 -1
  47. package/dist/frontend/types.js +20 -42
  48. package/dist/frontend/types.js.map +1 -1
  49. package/dist/index.d.ts +4 -1
  50. package/dist/index.js +219 -101
  51. package/dist/index.js.map +1 -1
  52. package/dist/ir/nodes.d.ts +6 -0
  53. package/dist/ir/nodes.js +28 -0
  54. package/dist/ir/nodes.js.map +1 -1
  55. package/dist/ir/validate.js +7 -1
  56. package/dist/ir/validate.js.map +1 -1
  57. package/dist/library/early-cache.js +4 -23
  58. package/dist/library/early-cache.js.map +1 -1
  59. package/dist/library/implementation-identity.d.ts +23 -0
  60. package/dist/library/implementation-identity.js +84 -0
  61. package/dist/library/implementation-identity.js.map +1 -0
  62. package/dist/startup-cache.d.ts +6 -0
  63. package/dist/startup-cache.js +6 -0
  64. package/dist/startup-cache.js.map +1 -0
  65. package/package.json +3 -2
  66. package/surface-manifest.json +1 -1
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
1
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
2
2
  import { basename, dirname, join, resolve } from "node:path";
3
- import { buildCacheRoot, CcCompileError, compileC, compileLibArchive, mobileLibraryTarget, mobileTargetRefusal, prepareBuildCacheRoot, pruneBuildCache, resolveCc, targetPlatform } from "./backend/cc.js";
3
+ import { buildCacheRoot, CcCompileError, compileC, compileLibArchive, executableNativeEnvironmentFingerprint, mobileLibraryTarget, mobileTargetRefusal, prepareBuildCacheRoot, pruneBuildCache, resolveCc, targetPlatform } from "./backend/cc.js";
4
4
  import { emitModule } from "./backend/emission/emitter.js";
5
5
  import { emitLlvmModule, LlvmUnsupportedError } from "./backend/llvm/emitter.js";
6
+ import { splitLlvmLibraryProgram, splitLlvmProgram } from "./backend/llvm/split.js";
6
7
  import { rebaseLibrarySourceComments, replaceLibraryIdentity, stripLibraryIdentity, stripLibrarySourceComments } from "./backend/library-identity.js";
7
8
  import { checkerPanicDiag, ffiNativeBuildDiag, libAsyncExportDiag, libAsyncSurfaceDiag, libExportUnresolvedDiag, libGenericExportDiag, libIntBoundaryDiag, libNpmIneligibleDiag, libSidecarDiag, libUnmappableSignatureDiag, iceDiag, isCheckerPanic, LIB_INBOUND_BYTES_TRAP_CODE, LIB_RUNTIME_TRAP_CODES } from "./diagnostics/diagnostic.js";
8
9
  import { checkLibraryIntegerSlots, classSeed, hasIntSlots, numberCarrierKind } from "./library/int-infer.js";
@@ -27,8 +28,10 @@ import { hasForeignFfiCallback } from "./backend/ffi-callbacks.js";
27
28
  import { FrontendInputTracker, trackedReadFile } from "./frontend/input-tracker.js";
28
29
  import { libraryFrontendImplementationFingerprint, publishEarlyLibraryCache, readEarlyLibraryCache, readSemanticLibraryCache } from "./library/early-cache.js";
29
30
  import { createSourceLineRebaser } from "./library/semantic-source.js";
31
+ import { publishEarlyExecutableCache, publishEarlyExecutableRoute, readEarlyExecutableCache } from "./executable/early-cache.js";
32
+ import { compilerImplementationIdentity } from "./library/implementation-identity.js";
30
33
  export const VERSION = "0.0.1";
31
- export { compileC, runtimeSrcDir } from "./backend/cc.js";
34
+ export { compileC, runtimeSrcDir, warmNativeCaches, } from "./backend/cc.js";
32
35
  export { ANDROID_MIN_API, IPHONEOS_MIN_VERSION, isAndroidTarget, isIosTarget, isMobileTarget, mobileLibraryTarget, mobileTargetRefusal } from "./backend/cc.js";
33
36
  export { emitModule } from "./backend/emission/emitter.js";
34
37
  export { renderAll, renderDiagnostic } from "./diagnostics/render.js";
@@ -629,13 +632,112 @@ export function analyze(entryPath, opts = {}) {
629
632
  }
630
633
  /** The whole pipeline: load → preflight → lower → validate → emit C → clang. */
631
634
  export async function compile(entryPath, opts) {
635
+ const frontendInputs = new FrontendInputTracker();
636
+ return frontendInputs.run(() => compileTracked(entryPath, opts, frontendInputs));
637
+ }
638
+ function executableNativeFeatures(mod, backend, dynamic, optimization, llvmRefusal) {
639
+ return {
640
+ backend,
641
+ ...(optimization === "dev" ? { optimization: "dev" } : {}),
642
+ ...(llvmRefusal === undefined ? {} : { llvmRefusal }),
643
+ dynamic,
644
+ regex: moduleUsesRegex(mod),
645
+ copying: moduleUsesCopying(mod),
646
+ textDecoderLegacy: moduleUsesLegacyTextDecoder(mod),
647
+ fileHandle: moduleUsesFileHandle(mod),
648
+ fetch: moduleUsesFetch(mod),
649
+ netIsland: moduleEmbedsBuiltin(mod, "node:http") ||
650
+ moduleEmbedsBuiltin(mod, "node:https") ||
651
+ moduleEmbedsBuiltin(mod, "node:net") ||
652
+ moduleEmbedsBuiltin(mod, "node:tls"),
653
+ zlib: moduleUsesZlib(mod) || moduleEmbedsCompressedNpm(mod),
654
+ assert: moduleUsesAssert(mod),
655
+ inspect: moduleUsesInspect(mod),
656
+ dynInvoke: moduleUsesDynInvoke(mod),
657
+ dc: moduleUsesDc(mod),
658
+ dynAsync: moduleUsesDynAsync(mod),
659
+ events: moduleUsesProcessEvents(mod),
660
+ emitter: moduleUsesEmitter(mod),
661
+ symbol: moduleUsesSymbol(mod),
662
+ searchParams: moduleUsesSearchParams(mod),
663
+ qs: moduleUsesQs(mod),
664
+ parseArgs: moduleUsesParseArgs(mod),
665
+ stream: moduleUsesStream(mod),
666
+ net: moduleUsesNet(mod),
667
+ http: moduleUsesHttpServer(mod),
668
+ http2: moduleUsesHttp2(mod),
669
+ dgram: moduleUsesDgram(mod),
670
+ watch: moduleUsesFsWatch(mod),
671
+ foreignFfi: hasForeignFfiCallback(mod.ffiImports ?? []),
672
+ nodeTest: moduleUsesNodeTest(mod),
673
+ tls: moduleUsesTls(mod),
674
+ tlsCa: moduleUsesTlsCa(mod),
675
+ };
676
+ }
677
+ async function compileExecutableNative(features, cPath, outPath, sanitize, ffi, programSplit = null, onArtifactReady) {
678
+ const effectiveProgramSplit = programSplit ??
679
+ (features.optimization === "dev" && features.backend === "llvm" && !sanitize
680
+ ? splitLlvmProgram(await readFile(cPath, "utf8"))
681
+ : null);
682
+ await compileC({
683
+ cPath,
684
+ outPath,
685
+ cacheIdentity: "scriptc-generated-v1",
686
+ ...(features.optimization === "dev" ? { optimization: "dev" } : {}),
687
+ ...(effectiveProgramSplit === null
688
+ ? {}
689
+ : {
690
+ programShards: effectiveProgramSplit.shards,
691
+ programPublicSymbols: effectiveProgramSplit.publicSymbols,
692
+ }),
693
+ sanitize,
694
+ dynamic: features.dynamic,
695
+ regex: features.regex,
696
+ copying: features.copying,
697
+ textDecoderLegacy: features.textDecoderLegacy,
698
+ fileHandle: features.fileHandle,
699
+ fetch: features.fetch,
700
+ netIsland: features.netIsland,
701
+ zlib: features.zlib,
702
+ assert: features.assert,
703
+ inspect: features.inspect,
704
+ dynInvoke: features.dynInvoke,
705
+ dc: features.dc,
706
+ dynAsync: features.dynAsync,
707
+ events: features.events,
708
+ emitter: features.emitter,
709
+ symbol: features.symbol,
710
+ searchParams: features.searchParams,
711
+ qs: features.qs,
712
+ parseArgs: features.parseArgs,
713
+ stream: features.stream,
714
+ net: features.net,
715
+ http: features.http,
716
+ http2: features.http2,
717
+ dgram: features.dgram,
718
+ watch: features.watch,
719
+ foreignFfi: features.foreignFfi,
720
+ nodeTest: features.nodeTest,
721
+ tls: features.tls,
722
+ tlsCa: features.tlsCa,
723
+ ...(onArtifactReady === undefined ? {} : { onArtifactReady }),
724
+ ...(ffi === null
725
+ ? {}
726
+ : { linkInputs: ffi.libraries, systemLibraries: ffi.systemLibraries }),
727
+ });
728
+ }
729
+ async function compileTracked(entryPath, opts, frontendInputs) {
730
+ entryPath = resolve(entryPath);
632
731
  let ffi = null;
732
+ let ffiProfileBytes = null;
633
733
  if (opts.ffiProfilePath !== undefined) {
634
- const loaded = loadFfiProfile(opts.ffiProfilePath);
734
+ const ffiProfilePath = resolve(opts.ffiProfilePath);
735
+ const loaded = loadFfiProfile(ffiProfilePath);
635
736
  if (!loaded.ok) {
636
737
  return { ok: false, diagnostics: loaded.diagnostics, sourceTexts: new Map() };
637
738
  }
638
739
  ffi = loaded.profile;
740
+ ffiProfileBytes = loaded.profileBytes;
639
741
  }
640
742
  const buildPlatform = buildTargetPlatform();
641
743
  // Mobile triples are library-mode targets: the archive an embedding app
@@ -664,6 +766,81 @@ export async function compile(entryPath, opts) {
664
766
  };
665
767
  }
666
768
  }
769
+ const cacheRoot = provenanceSources() === null
770
+ ? await prepareBuildCacheRoot(buildCacheRoot())
771
+ : null;
772
+ const implementation = await compilerImplementationIdentity();
773
+ const earlyCacheOptions = {
774
+ entryPath,
775
+ outDir: opts.outDir,
776
+ outPath: opts.outPath,
777
+ emitIr: opts.emitIr ?? false,
778
+ sanitize: opts.sanitize ?? false,
779
+ dynamic: opts.dynamic ?? false,
780
+ backend: opts.backend ?? "auto",
781
+ ...(opts.optimization === "dev" ? { optimization: "dev" } : {}),
782
+ npmStatic: opts.npmStatic ?? null,
783
+ ffiProfile: opts.ffiProfilePath === undefined || ffiProfileBytes === null
784
+ ? null
785
+ : { path: opts.ffiProfilePath, bytes: ffiProfileBytes },
786
+ target: `${process.env["SCRIPTC_TARGET"] ?? "native"}:${buildPlatform}:${process.arch}`,
787
+ compiler: [process.env["SCRIPTC_CC"] ?? "clang"],
788
+ nativeEnvironment: await executableNativeEnvironmentFingerprint(),
789
+ nodeVersion: process.version,
790
+ implementation: implementation.digest,
791
+ implementationDependencies: implementation.dependencies,
792
+ };
793
+ const earlyHit = await readEarlyExecutableCache(cacheRoot, earlyCacheOptions);
794
+ if (earlyHit !== null) {
795
+ // Route/proof metadata is independently evictable. A full-compiler
796
+ // fallback that still finds the validated payload repairs that lightweight
797
+ // index so the next identical CLI invocation can avoid this module graph.
798
+ await publishEarlyExecutableRoute(cacheRoot, earlyCacheOptions).catch(() => undefined);
799
+ if (earlyHit.executableRestored) {
800
+ await pruneBuildCache(cacheRoot);
801
+ return {
802
+ ok: true,
803
+ binaryPath: opts.outPath,
804
+ cPath: earlyHit.cPath,
805
+ backend: earlyHit.native.backend,
806
+ ...(earlyHit.irPath === undefined ? {} : { irPath: earlyHit.irPath }),
807
+ ...(earlyHit.native.llvmRefusal === undefined
808
+ ? {}
809
+ : { llvmRefusal: earlyHit.native.llvmRefusal }),
810
+ };
811
+ }
812
+ try {
813
+ await compileExecutableNative(earlyHit.native, earlyHit.cPath, opts.outPath, opts.sanitize ?? false, ffi, null, async ({ dependencies }) => {
814
+ await publishEarlyExecutableCache(cacheRoot, earlyCacheOptions, {
815
+ ...earlyHit,
816
+ executableRestored: true,
817
+ nativeDependencies: dependencies,
818
+ frontend: earlyHit.frontend,
819
+ });
820
+ });
821
+ }
822
+ catch (err) {
823
+ if (ffi !== null && err instanceof CcCompileError) {
824
+ return {
825
+ ok: false,
826
+ diagnostics: [ffiNativeBuildDiag(ffiNativeBuildDetail(err), opts.ffiProfilePath ?? entryPath)],
827
+ sourceTexts: new Map(),
828
+ };
829
+ }
830
+ throw err;
831
+ }
832
+ await pruneBuildCache(cacheRoot);
833
+ return {
834
+ ok: true,
835
+ binaryPath: opts.outPath,
836
+ cPath: earlyHit.cPath,
837
+ backend: earlyHit.native.backend,
838
+ ...(earlyHit.irPath === undefined ? {} : { irPath: earlyHit.irPath }),
839
+ ...(earlyHit.native.llvmRefusal === undefined
840
+ ? {}
841
+ : { llvmRefusal: earlyHit.native.llvmRefusal }),
842
+ };
843
+ }
667
844
  const fe = runFrontend(entryPath, opts.npmStatic);
668
845
  let lowered;
669
846
  let entryText;
@@ -737,6 +914,7 @@ export async function compile(entryPath, opts) {
737
914
  // (the frontend ran once, the IR is backend-agnostic — nothing recompiles).
738
915
  let cPath = join(opts.outDir, `${stem}.c`);
739
916
  let backend = "c";
917
+ let llvmSource = null;
740
918
  let llvmRefusal;
741
919
  if (opts.backend !== "c") {
742
920
  try {
@@ -746,6 +924,7 @@ export async function compile(entryPath, opts) {
746
924
  });
747
925
  cPath = join(opts.outDir, `${stem}.ll`);
748
926
  await writeFile(cPath, ll);
927
+ llvmSource = ll;
749
928
  backend = "llvm";
750
929
  }
751
930
  catch (err) {
@@ -772,105 +951,24 @@ export async function compile(entryPath, opts) {
772
951
  irPath = join(opts.outDir, `${stem}.ir.json`);
773
952
  await writeFile(irPath, serializeModule(lowered.module));
774
953
  }
954
+ const nativeFeatures = executableNativeFeatures(lowered.module, backend, opts.dynamic ?? false, opts.optimization ?? "release", llvmRefusal);
955
+ const programSplit = backend === "llvm" && (opts.optimization ?? "release") === "dev" &&
956
+ !(opts.sanitize ?? false) && llvmSource !== null
957
+ ? splitLlvmProgram(llvmSource)
958
+ : null;
775
959
  await mkdir(dirname(opts.outPath), { recursive: true });
960
+ let publishedExecutable = false;
776
961
  try {
777
- await compileC({
778
- cPath,
779
- outPath: opts.outPath,
780
- // The emitted TU's non-system dependencies are the runtime/vendor tree,
781
- // which cc.ts fingerprints separately. Low-level arbitrary C omits this
782
- // opt-in so same-path header edits can never hit a stale artifact.
783
- cacheIdentity: "scriptc-generated-v1",
784
- sanitize: opts.sanitize ?? false,
785
- dynamic: opts.dynamic ?? false,
786
- // The link switch for scr_regex.c + libregexp: detected on the IR, so
787
- // regex-free programs keep the historical (pinned) command line.
788
- regex: moduleUsesRegex(lowered.module),
789
- // Array copying methods and the typed-array bridges live in one
790
- // optional TU, linked only when one of their IR intrinsics survives.
791
- copying: moduleUsesCopying(lowered.module),
792
- textDecoderLegacy: moduleUsesLegacyTextDecoder(lowered.module),
793
- // FileHandle owns a native descriptor and its settled-promise adapters;
794
- // keep that optional TU out of programs that never call fsp.open.
795
- fileHandle: moduleUsesFileHandle(lowered.module),
796
- // The link switch for scr_fetch.c (the native bridge over scr_net +
797
- // scr_tls + scr_http's client parser + zlib — cc.ts implies those
798
- // units into the link): embedded npm code that references fetch gets
799
- // the bridge; everything else keeps its exact link line.
800
- fetch: moduleUsesFetch(lowered.module),
801
- // The island's node:http/https client bridge: embedded graphs that
802
- // import those builtins pull scr_net_island.c + the socket units.
803
- netIsland: moduleEmbedsBuiltin(lowered.module, "node:http") ||
804
- moduleEmbedsBuiltin(lowered.module, "node:https") ||
805
- moduleEmbedsBuiltin(lowered.module, "node:net") ||
806
- moduleEmbedsBuiltin(lowered.module, "node:tls"),
807
- // The link switch for scr_zlib.c + libz: zlib.* libCalls on the IR,
808
- // node:zlib in the embedded graph, or COMPRESSED embedded module text
809
- // (emit-island.ts stores big npm sources as raw DEFLATE; the emitted
810
- // main installs scr_zlib_inflate_exact on the same predicate).
811
- zlib: moduleUsesZlib(lowered.module) || moduleEmbedsCompressedNpm(lowered.module),
812
- // The link switch for scr_assert.c: assert.* libCalls on the IR (the
813
- // regex switch also pulls it — scr_regex.c calls the assert helpers).
814
- assert: moduleUsesAssert(lowered.module),
815
- // The link switch for scr_inspect.c: insp.* libCalls on the IR.
816
- inspect: moduleUsesInspect(lowered.module),
817
- // The link switch for scr_dyn_invoke.c: dynInvoke nodes or
818
- // dyn.defineProps libCalls on the IR.
819
- dynInvoke: moduleUsesDynInvoke(lowered.module),
820
- // The link switch for scr_dc.c: dc.* libCalls on the IR (the
821
- // diagnostics_channel registry and pub/sub).
822
- dc: moduleUsesDc(lowered.module),
823
- // The link switch for scr_async_dyn.c: the checked-dynamic async
824
- // surfaces (cc.ts also pulls it under the dynInvoke/dc gates).
825
- dynAsync: moduleUsesDynAsync(lowered.module),
826
- // The link switch for scr_events.c: process signal/exit listeners and
827
- // the stdin event surface on the IR.
828
- events: moduleUsesProcessEvents(lowered.module),
829
- // The link switch for scr_events_emitter.c: the node:events
830
- // EventEmitter surface on the IR (emitter.* libCalls or the
831
- // %EventEmitter class def).
832
- emitter: moduleUsesEmitter(lowered.module),
833
- // The link switch for scr_symbol.c: sym.* libCalls or a symbol-kind
834
- // type anywhere on the IR.
835
- symbol: moduleUsesSymbol(lowered.module),
836
- // The link switch for scr_url_params.c: sp.* libCalls, the
837
- // url.searchParams getter, or a searchParams-kind type on the IR.
838
- searchParams: moduleUsesSearchParams(lowered.module),
839
- // The link switch for scr_qs.c: the qs.* libCalls that live there
840
- // (parse/stringify/unescape; escape rides the always-linked encoder).
841
- qs: moduleUsesQs(lowered.module),
842
- // The static node:util parseArgs implementation (scr_util.c).
843
- parseArgs: moduleUsesParseArgs(lowered.module),
844
- // The link switch for scr_stream.c: the node:stream class surface on
845
- // the IR (stream libCalls or the %Readable-family class defs).
846
- stream: moduleUsesStream(lowered.module),
847
- // The link switch for scr_net.c: net.* (or http.* — http rides on
848
- // net) libCalls on the IR.
849
- net: moduleUsesNet(lowered.module),
850
- // The link switch for scr_http.c: http.* libCalls on the IR.
851
- http: moduleUsesHttpServer(lowered.module),
852
- http2: moduleUsesHttp2(lowered.module),
853
- // The link switch for scr_dgram.c: dgram.* or dns.* libCalls on the IR.
854
- dgram: moduleUsesDgram(lowered.module),
855
- // The link switch for scr_watch.c: fs.watch/watcher.* libCalls on the IR.
856
- watch: moduleUsesFsWatch(lowered.module),
857
- foreignFfi: hasForeignFfiCallback(lowered.module.ffiImports ?? []),
858
- // The link switch for scr_test.c: test.* libCalls on the IR.
859
- nodeTest: moduleUsesNodeTest(lowered.module),
860
- // The link switch for scr_tls.c + the vendored mbedTLS archive:
861
- // tls.* or https.* libCalls on the IR.
862
- tls: moduleUsesTls(lowered.module),
863
- // The link switch for scr_tls_ca.c (the CA-store introspection unit
864
- // — plain PEM bookkeeping, no mbedTLS): tlsca.* libCalls on the IR.
865
- // cc.ts also compiles it under the tls gate (scr_tls.c consults the
866
- // unit's default-set override for its trust anchors).
867
- tlsCa: moduleUsesTlsCa(lowered.module),
868
- ...(ffi !== null
869
- ? {
870
- linkInputs: ffi.libraries,
871
- systemLibraries: ffi.systemLibraries,
872
- }
873
- : {}),
962
+ await compileExecutableNative(nativeFeatures, cPath, opts.outPath, opts.sanitize ?? false, ffi, programSplit, async ({ dependencies }) => {
963
+ await publishEarlyExecutableCache(cacheRoot, earlyCacheOptions, {
964
+ cPath,
965
+ native: nativeFeatures,
966
+ executableRestored: true,
967
+ nativeDependencies: dependencies,
968
+ frontend: frontendInputs.snapshot(),
969
+ ...(irPath === undefined ? {} : { irPath }),
970
+ });
971
+ publishedExecutable = true;
874
972
  });
875
973
  }
876
974
  catch (err) {
@@ -885,6 +983,16 @@ export async function compile(entryPath, opts) {
885
983
  }
886
984
  throw err;
887
985
  }
986
+ if (!publishedExecutable) {
987
+ await publishEarlyExecutableCache(cacheRoot, earlyCacheOptions, {
988
+ cPath,
989
+ native: nativeFeatures,
990
+ executableRestored: false,
991
+ frontend: frontendInputs.snapshot(),
992
+ ...(irPath === undefined ? {} : { irPath }),
993
+ }).catch(() => undefined);
994
+ }
995
+ await pruneBuildCache(cacheRoot);
888
996
  return {
889
997
  ok: true,
890
998
  binaryPath: opts.outPath,
@@ -1245,7 +1353,8 @@ async function compileLibraryNative(profile, cPath, archivePath, sanitize, featu
1245
1353
  const localizeSymbols = libraryLocalizeSymbols(profile);
1246
1354
  let identityCSource;
1247
1355
  let programSource;
1248
- if (profile.sidecar !== null || profile.emission === "c") {
1356
+ if (profile.sidecar !== null || profile.emission === "c" ||
1357
+ (profile.emission === "llvm" && profile.optimization === "dev" && !sanitize)) {
1249
1358
  const publicSource = await readFile(cPath, "utf8");
1250
1359
  programSource = publicSource;
1251
1360
  }
@@ -1268,10 +1377,19 @@ async function compileLibraryNative(profile, cPath, archivePath, sanitize, featu
1268
1377
  if (profile.emission === "c") {
1269
1378
  programSource = stripLibrarySourceComments(programSource, profile.entry);
1270
1379
  }
1380
+ const llvmSplit = profile.emission === "llvm" && profile.optimization === "dev" && !sanitize && programSource !== undefined
1381
+ ? splitLlvmLibraryProgram(programSource)
1382
+ : null;
1271
1383
  await compileLibArchive({
1272
1384
  cPath,
1273
1385
  ...(programSource !== undefined ? { programSource } : {}),
1274
1386
  ...(identityCSource !== undefined ? { identityCSource } : {}),
1387
+ ...(llvmSplit !== null
1388
+ ? {
1389
+ programShards: llvmSplit.shards,
1390
+ programPublicSymbols: llvmSplit.publicSymbols,
1391
+ }
1392
+ : {}),
1275
1393
  outPath: archivePath,
1276
1394
  cacheIdentity: "scriptc-generated-library-v1",
1277
1395
  sanitize,