@scriptc/compiler 0.0.33 → 0.0.34

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 (102) hide show
  1. package/dist/backend/cc-cache.test.js +122 -0
  2. package/dist/backend/cc-cache.test.js.map +1 -1
  3. package/dist/backend/cc.d.ts +19 -0
  4. package/dist/backend/cc.js +111 -20
  5. package/dist/backend/cc.js.map +1 -1
  6. package/dist/backend/emission/emit-exprs.js +26 -1
  7. package/dist/backend/emission/emit-exprs.js.map +1 -1
  8. package/dist/backend/emission/emit-shapes.js +37 -4
  9. package/dist/backend/emission/emit-shapes.js.map +1 -1
  10. package/dist/backend/emission/emitter.d.ts +11 -2
  11. package/dist/backend/emission/emitter.js +11 -5
  12. package/dist/backend/emission/emitter.js.map +1 -1
  13. package/dist/backend/library-identity.d.ts +22 -0
  14. package/dist/backend/library-identity.js +103 -0
  15. package/dist/backend/library-identity.js.map +1 -0
  16. package/dist/backend/llvm/emitter.d.ts +3 -0
  17. package/dist/backend/llvm/emitter.js +35 -5
  18. package/dist/backend/llvm/emitter.js.map +1 -1
  19. package/dist/backend/llvm/shapes.d.ts +1 -0
  20. package/dist/backend/llvm/shapes.js +25 -1
  21. package/dist/backend/llvm/shapes.js.map +1 -1
  22. package/dist/backend/mangle.d.ts +1 -0
  23. package/dist/backend/mangle.js +3 -0
  24. package/dist/backend/mangle.js.map +1 -1
  25. package/dist/backend/object-localize.d.ts +5 -5
  26. package/dist/backend/object-localize.js +19 -16
  27. package/dist/backend/object-localize.js.map +1 -1
  28. package/dist/backend/object-localize.test.js +37 -13
  29. package/dist/backend/object-localize.test.js.map +1 -1
  30. package/dist/frontend/input-tracker.d.ts +82 -0
  31. package/dist/frontend/input-tracker.js +380 -0
  32. package/dist/frontend/input-tracker.js.map +1 -0
  33. package/dist/frontend/input-tracker.test.d.ts +1 -0
  34. package/dist/frontend/input-tracker.test.js +137 -0
  35. package/dist/frontend/input-tracker.test.js.map +1 -0
  36. package/dist/frontend/lowering/lower-builtins.js +2 -8
  37. package/dist/frontend/lowering/lower-builtins.js.map +1 -1
  38. package/dist/frontend/lowering/lower-calls.js +155 -140
  39. package/dist/frontend/lowering/lower-calls.js.map +1 -1
  40. package/dist/frontend/lowering/lower-classes.js +3 -0
  41. package/dist/frontend/lowering/lower-classes.js.map +1 -1
  42. package/dist/frontend/lowering/lower-containers.js +48 -9
  43. package/dist/frontend/lowering/lower-containers.js.map +1 -1
  44. package/dist/frontend/lowering/lower-exprs.js +67 -1
  45. package/dist/frontend/lowering/lower-exprs.js.map +1 -1
  46. package/dist/frontend/lowering/lower-inspect.js +45 -26
  47. package/dist/frontend/lowering/lower-inspect.js.map +1 -1
  48. package/dist/frontend/lowering/lower-modules.js +1 -1
  49. package/dist/frontend/lowering/lower-modules.js.map +1 -1
  50. package/dist/frontend/lowering/lower-stmts.js +48 -3
  51. package/dist/frontend/lowering/lower-stmts.js.map +1 -1
  52. package/dist/frontend/lowering/lowerer.d.ts +67 -29
  53. package/dist/frontend/lowering/lowerer.js +410 -87
  54. package/dist/frontend/lowering/lowerer.js.map +1 -1
  55. package/dist/frontend/npm-static-rewrite.js +25 -26
  56. package/dist/frontend/npm-static-rewrite.js.map +1 -1
  57. package/dist/frontend/npm-static.js +29 -30
  58. package/dist/frontend/npm-static.js.map +1 -1
  59. package/dist/frontend/npm-static.test.d.ts +1 -0
  60. package/dist/frontend/npm-static.test.js +15 -0
  61. package/dist/frontend/npm-static.test.js.map +1 -0
  62. package/dist/frontend/npm.js +5 -17
  63. package/dist/frontend/npm.js.map +1 -1
  64. package/dist/frontend/program.js +2 -6
  65. package/dist/frontend/program.js.map +1 -1
  66. package/dist/frontend/resolve.js +8 -29
  67. package/dist/frontend/resolve.js.map +1 -1
  68. package/dist/frontend/ts7/program.js +17 -18
  69. package/dist/frontend/ts7/program.js.map +1 -1
  70. package/dist/frontend/types.d.ts +33 -0
  71. package/dist/frontend/types.js +114 -3
  72. package/dist/frontend/types.js.map +1 -1
  73. package/dist/index.d.ts +1 -1
  74. package/dist/index.js +241 -42
  75. package/dist/index.js.map +1 -1
  76. package/dist/ir/nodes.d.ts +21 -4
  77. package/dist/ir/nodes.js.map +1 -1
  78. package/dist/ir/serialize.d.ts +1 -1
  79. package/dist/ir/serialize.js +1 -1
  80. package/dist/ir/validate.js +31 -1
  81. package/dist/ir/validate.js.map +1 -1
  82. package/dist/library/early-cache.d.ts +65 -0
  83. package/dist/library/early-cache.js +380 -0
  84. package/dist/library/early-cache.js.map +1 -0
  85. package/dist/library/early-cache.test.d.ts +1 -0
  86. package/dist/library/early-cache.test.js +528 -0
  87. package/dist/library/early-cache.test.js.map +1 -0
  88. package/dist/library/int-infer.js +14 -0
  89. package/dist/library/int-infer.js.map +1 -1
  90. package/dist/library/int-infer.test.js +21 -4
  91. package/dist/library/int-infer.test.js.map +1 -1
  92. package/dist/library/semantic-source.d.ts +13 -0
  93. package/dist/library/semantic-source.js +257 -0
  94. package/dist/library/semantic-source.js.map +1 -0
  95. package/dist/library/semantic-source.test.d.ts +1 -0
  96. package/dist/library/semantic-source.test.js +113 -0
  97. package/dist/library/semantic-source.test.js.map +1 -0
  98. package/dist/library/sidecar.d.ts +6 -0
  99. package/dist/library/sidecar.js +11 -0
  100. package/dist/library/sidecar.js.map +1 -1
  101. package/package.json +2 -2
  102. package/surface-manifest.json +1 -1
@@ -271,6 +271,15 @@ export declare function vendorCacheBuildIdentity(environmentFingerprint: string,
271
271
  export interface LibArchiveOptions {
272
272
  /** The program TU (.c or .ll — clang compiles either with -c). */
273
273
  cPath: string;
274
+ /** Invocation-owned program source to compile under `cPath`'s public
275
+ * spelling. Library assembly uses this for the identity-free projection of
276
+ * a complete caller-visible TU; its bytes drive every native cache key. */
277
+ programSource?: string;
278
+ /** Tiny generated C source carrying volatile library identity getters.
279
+ * Its bytes join the complete archive key, but the source itself exists
280
+ * only in the invocation-private build directory and the large program-
281
+ * object cache is keyed independently. */
282
+ identityCSource?: string;
274
283
  /** The archive to produce (<name>.lib.a). */
275
284
  outPath: string;
276
285
  /** Caller-owned identity for the generated TU's complete non-system
@@ -318,6 +327,16 @@ export declare function compileLibArchive(opts: LibArchiveOptions): Promise<void
318
327
  /** Resolve the build cache without touching the filesystem. Exported from this
319
328
  * internal module so its platform and override behavior can be pinned directly. */
320
329
  export declare function resolveBuildCacheRoot(env?: NodeJS.ProcessEnv, platform?: NodeJS.Platform, userHome?: string): string | null;
330
+ /** Shared persistent-cache root for compiler-level tiers. The early library
331
+ * cache deliberately follows the native cache's activation and hard-disable
332
+ * contract, while native compilation retains ownership of toolchain safety. */
333
+ export declare function buildCacheRoot(): string | null;
334
+ /** Harden/create a compiler-level cache root using the same privacy policy as
335
+ * the artifact caches. Failure disables only the optional caller's tier. */
336
+ export declare function prepareBuildCacheRoot(root: string | null): Promise<string | null>;
337
+ /** Register a successful compiler-level cache write with the shared bounded
338
+ * LRU policy. */
339
+ export declare function pruneBuildCache(root: string | null): Promise<void>;
321
340
  export declare function ccVersionOnce(argv: string[], environmentFingerprint?: string, fresh?: boolean): Promise<string>;
322
341
  /** Every system-header spelling consumed by a source tree scriptc owns. The
323
342
  * dependency probe preprocesses these spellings with the selected driver and
@@ -1087,24 +1087,26 @@ export async function compileLibArchive(opts) {
1087
1087
  let archiverVersion = "";
1088
1088
  let runtimeHash = "";
1089
1089
  let programDependencyHash = "";
1090
- let cachedProgramBytes = null;
1090
+ let cachedProgramBytes = opts.programSource === undefined
1091
+ ? null
1092
+ : Buffer.from(opts.programSource, "utf8");
1093
+ const identityBytes = opts.identityCSource === undefined
1094
+ ? null
1095
+ : Buffer.from(opts.identityCSource, "utf8");
1091
1096
  if (root !== null) {
1092
1097
  try {
1093
1098
  const [cv, fingerprint, programBytes] = await Promise.all([
1094
1099
  ccVersionOnce(driver.argv, toolchainEnv, true),
1095
1100
  runtimeFingerprint(rtDir),
1096
- readFile(opts.cPath),
1101
+ cachedProgramBytes === null ? readFile(opts.cPath) : Promise.resolve(cachedProgramBytes),
1097
1102
  ]);
1098
1103
  compilerVersion = cv;
1099
1104
  runtimeHash = fingerprint;
1100
1105
  cachedProgramBytes = programBytes;
1106
+ programDependencyHash = await translationUnitDependencyFingerprint(driver, cflags, opts.cPath, programBytes, toolchainEnv);
1101
1107
  if (cacheCompleteArchive) {
1102
- const [av, programDependencies] = await Promise.all([
1103
- toolVersionOnce(arArgv, toolchainEnv, true),
1104
- translationUnitDependencyFingerprint(driver, cflags, opts.cPath, programBytes, toolchainEnv),
1105
- ]);
1108
+ const av = await toolVersionOnce(arArgv, toolchainEnv, true);
1106
1109
  archiverVersion = av;
1107
- programDependencyHash = programDependencies;
1108
1110
  const key = createHash("sha256")
1109
1111
  // v7 adds effective compiler-wrapper invocations for the real runtime
1110
1112
  // and program compile flavors.
@@ -1114,7 +1116,7 @@ export async function compileLibArchive(opts) {
1114
1116
  .update(implicitToolchain).update("\0")
1115
1117
  .update(runtimeCompilerInvocation).update("\0")
1116
1118
  .update(programCompilerInvocation).update("\0")
1117
- .update(programDependencies).update("\0")
1119
+ .update(programDependencyHash).update("\0")
1118
1120
  .update(opts.cacheIdentity).update("\0")
1119
1121
  .update(driver.argv.join("\x1f")).update("\0")
1120
1122
  .update(cv).update("\0")
@@ -1129,6 +1131,9 @@ export async function compileLibArchive(opts) {
1129
1131
  .update(opts.cPath).update("\0")
1130
1132
  .update(resolve(opts.cPath)).update("\0")
1131
1133
  .update(programBytes)
1134
+ .update("\0identity\0")
1135
+ .update(identityBytes === null ? "<none>" : "<generated>").update("\0")
1136
+ .update(identityBytes ?? Buffer.alloc(0))
1132
1137
  .digest("hex");
1133
1138
  cachedArchive = join(root, "lib", key);
1134
1139
  const tmpOut = privateSiblingPath(opts.outPath, "lib-hit");
@@ -1200,7 +1205,64 @@ export async function compileLibArchive(opts) {
1200
1205
  : join(buildDir, `program${opts.cPath.endsWith(".ll") ? ".ll" : ".c"}`);
1201
1206
  if (cachedProgramBytes !== null)
1202
1207
  await writeFile(programSource, cachedProgramBytes);
1203
- const programObject = await compileOne(programSource, `${stem}.program.o`, cachedProgramBytes === null ? undefined : opts.cPath);
1208
+ let cachedProgramObject = null;
1209
+ if (root !== null && cachedProgramBytes !== null && compilerVersion !== "" &&
1210
+ implicitToolchain !== null && programCompilerInvocation !== null) {
1211
+ const programKey = createHash("sha256")
1212
+ .update("lib-program-obj-v1\0")
1213
+ .update(cacheTargetIdentity(driver)).update("\0")
1214
+ .update(toolchainEnv).update("\0")
1215
+ .update(implicitToolchain).update("\0")
1216
+ .update(programCompilerInvocation).update("\0")
1217
+ .update(opts.cacheIdentity).update("\0")
1218
+ .update(driver.argv.join("\x1f")).update("\0")
1219
+ .update(compilerVersion).update("\0")
1220
+ .update(runtimeHash).update("\0")
1221
+ .update(programDependencyHash).update("\0")
1222
+ .update(programCompilerArgs.join("\x1f")).update("\0")
1223
+ .update(opts.cPath).update("\0")
1224
+ .update(resolve(opts.cPath)).update("\0")
1225
+ .update(cachedProgramBytes)
1226
+ .digest("hex");
1227
+ cachedProgramObject = join(root, "program-obj", programKey);
1228
+ }
1229
+ const stagedProgramObject = join(buildDir, `${stem}.program.o`);
1230
+ let programObject;
1231
+ if (cachedProgramObject !== null &&
1232
+ await copyValidCachedFile(cachedProgramObject, stagedProgramObject)) {
1233
+ programObject = stagedProgramObject;
1234
+ }
1235
+ else {
1236
+ programObject = await compileOne(programSource, `${stem}.program.o`, cachedProgramBytes === null ? undefined : opts.cPath);
1237
+ if (cachedProgramObject !== null) {
1238
+ try {
1239
+ const [currentRuntime, currentImplicit, currentInvocation, currentDependencies, currentCompiler] = await Promise.all([
1240
+ runtimeFingerprint(rtDir),
1241
+ implicitToolchainFingerprint(driver, toolchainEnv),
1242
+ effectiveCompilerInvocationFingerprint(driver, toolchainEnv, programCompilerArgs, programSourceExtension),
1243
+ translationUnitDependencyFingerprint(driver, cflags, opts.cPath, cachedProgramBytes, toolchainEnv),
1244
+ ccVersionOnce(driver.argv, toolchainEnv, true),
1245
+ ]);
1246
+ if (currentRuntime === runtimeHash &&
1247
+ currentImplicit === implicitToolchain &&
1248
+ currentInvocation === programCompilerInvocation &&
1249
+ currentDependencies === programDependencyHash &&
1250
+ currentCompiler === compilerVersion) {
1251
+ await publishCachedFile(programObject, cachedProgramObject);
1252
+ }
1253
+ }
1254
+ catch {
1255
+ // Best-effort: the archive build already owns a valid object.
1256
+ }
1257
+ }
1258
+ }
1259
+ const identityObject = identityBytes === null
1260
+ ? null
1261
+ : await (async () => {
1262
+ const source = join(buildDir, "identity.c");
1263
+ await writeFile(source, identityBytes);
1264
+ return compileOne(source, `${stem}.identity.o`);
1265
+ })();
1204
1266
  let runtimeObjects = null;
1205
1267
  let cacheInputsStable = true;
1206
1268
  let objectImplicitVerification = null;
@@ -1233,14 +1295,14 @@ export async function compileLibArchive(opts) {
1233
1295
  runtimeObjects.push(...(await Promise.all(sources.slice(i, i + width).map((f) => compileOne(join(rtDir, f), f.replace(/\.c$/, ".o"))))));
1234
1296
  }
1235
1297
  }
1236
- const objects = [programObject, ...runtimeObjects, ...lreObjects, ...zlibObjects];
1298
+ const objects = [programObject, ...(identityObject === null ? [] : [identityObject]), ...runtimeObjects, ...lreObjects, ...zlibObjects];
1237
1299
  // Multi-instance library mode: the archive's one member becomes the
1238
1300
  // combined, symbol-localized object (cached vendor/runtime objects
1239
1301
  // are read-only inputs here — the combine step never mutates them).
1240
1302
  const archiveMembers = opts.localizeSymbols === undefined
1241
1303
  ? objects
1242
1304
  : [
1243
- await localizeLibraryObjects(driver, arArgv, buildDir, programObject, [...runtimeObjects, ...lreObjects, ...zlibObjects], opts.localizeSymbols, stem),
1305
+ await localizeLibraryObjects(driver, arArgv, buildDir, [programObject, ...(identityObject === null ? [] : [identityObject])], [...runtimeObjects, ...lreObjects, ...zlibObjects], opts.localizeSymbols, stem),
1244
1306
  ];
1245
1307
  // A cacheable or runtime-localized build owns a private archive from
1246
1308
  // `ar` through publication. Localized archives deliberately bypass the
@@ -1320,7 +1382,8 @@ export async function compileLibArchive(opts) {
1320
1382
  * shared by design. Windows embedders additionally link advapi32, iphlpapi,
1321
1383
  * and ws2_32.
1322
1384
  *
1323
- * Member selection matters: a classic archive's unused members (and their
1385
+ * The generated program and optional identity objects are mandatory roots;
1386
+ * support-member selection still matters. A classic archive's unused members (and their
1324
1387
  * undefined references to units library mode excludes, like the
1325
1388
  * fs-promises unit's fiber symbols) never reach an embedder's link. A
1326
1389
  * blind merge of every object would carry those references into the one
@@ -1329,7 +1392,7 @@ export async function compileLibArchive(opts) {
1329
1392
  * members the program object transitively needs (the COFF arm implements
1330
1393
  * the same member semantics in process).
1331
1394
  *
1332
- * Mach-O — one host-ld64 invocation: -r merges program + needed members,
1395
+ * Mach-O — one host-ld64 invocation: -r merges roots + needed members,
1333
1396
  * -exported_symbols_list demotes every unlisted global to
1334
1397
  * private extern, and -r without -keep_private_externs writes
1335
1398
  * private externs out as non-external symbols. Apple ASan's
@@ -1360,7 +1423,7 @@ export async function compileLibArchive(opts) {
1360
1423
  * mirrors MSVC link.exe; zig's COFF driver refuses multi-object
1361
1424
  * merges) and llvm-objcopy rejects symbol-scope flags for
1362
1425
  * COFF, so no tool pairing exists to shell out to. */
1363
- async function localizeLibraryObjects(driver, arArgv, buildDir, programObject, supportObjects, keepSymbols, stem) {
1426
+ async function localizeLibraryObjects(driver, arArgv, buildDir, rootObjects, supportObjects, keepSymbols, stem) {
1364
1427
  const platform = targetPlatform(driver);
1365
1428
  const combined = join(buildDir, `${stem}.localized.o`);
1366
1429
  const staging = join(buildDir, `${stem}.localize-staging.a`);
@@ -1378,10 +1441,13 @@ async function localizeLibraryObjects(driver, arArgv, buildDir, programObject, s
1378
1441
  if (platform === "win32") {
1379
1442
  // COFF has no relocatable-link tool to stage through; the member
1380
1443
  // selection and combine+demote happen in process over the object bytes.
1381
- const [program, ...support] = await Promise.all([programObject, ...supportObjects].map((path) => readFile(path)));
1444
+ const [roots, support] = await Promise.all([
1445
+ Promise.all(rootObjects.map((path) => readFile(path))),
1446
+ Promise.all(supportObjects.map((path) => readFile(path))),
1447
+ ]);
1382
1448
  try {
1383
- await writeFile(combined, mergeAndLocalizeCoffObjects(program, support, new Set(keepSymbols), {
1384
- program: basename(programObject),
1449
+ await writeFile(combined, mergeAndLocalizeCoffObjects(roots, support, new Set(keepSymbols), {
1450
+ roots: rootObjects.map((path) => basename(path)),
1385
1451
  support: supportObjects.map((path) => basename(path)),
1386
1452
  }));
1387
1453
  }
@@ -1393,11 +1459,11 @@ async function localizeLibraryObjects(driver, arArgv, buildDir, programObject, s
1393
1459
  await run([arArgv[0] ?? "ar", ...arArgv.slice(1), "rcs", staging, ...supportObjects]);
1394
1460
  if (platform === "darwin") {
1395
1461
  await writeFile(keepFile, keepSymbols.map((s) => `_${s}\n`).join(""));
1396
- await run(["ld", "-r", programObject, staging, "-o", combined, "-exported_symbols_list", keepFile]);
1462
+ await run(["ld", "-r", ...rootObjects, staging, "-o", combined, "-exported_symbols_list", keepFile]);
1397
1463
  }
1398
1464
  else if (platform === "linux" && driver.target === null) {
1399
1465
  await writeFile(keepFile, keepSymbols.map((s) => `${s}\n`).join(""));
1400
- await run(["ld", "-r", "--force-group-allocation", programObject, staging, "-o", combined]);
1466
+ await run(["ld", "-r", "--force-group-allocation", ...rootObjects, staging, "-o", combined]);
1401
1467
  await run(["objcopy", `--keep-global-symbols=${keepFile}`, combined]);
1402
1468
  }
1403
1469
  else if (platform === "linux") {
@@ -1412,7 +1478,7 @@ async function localizeLibraryObjects(driver, arArgv, buildDir, programObject, s
1412
1478
  ...driver.argv.slice(1),
1413
1479
  "-target", driver.zigTarget ?? driver.target,
1414
1480
  "-nostdlib",
1415
- "-r", programObject, staging,
1481
+ "-r", ...rootObjects, staging,
1416
1482
  "-o", combined,
1417
1483
  ]);
1418
1484
  try {
@@ -1521,6 +1587,31 @@ export function resolveBuildCacheRoot(env = process.env, platform = process.plat
1521
1587
  ? resolve(userHome, "Library", "Caches", "scriptc", "build")
1522
1588
  : resolve(userHome, ".cache", "scriptc", "build");
1523
1589
  }
1590
+ /** Shared persistent-cache root for compiler-level tiers. The early library
1591
+ * cache deliberately follows the native cache's activation and hard-disable
1592
+ * contract, while native compilation retains ownership of toolchain safety. */
1593
+ export function buildCacheRoot() {
1594
+ return resolveBuildCacheRoot();
1595
+ }
1596
+ /** Harden/create a compiler-level cache root using the same privacy policy as
1597
+ * the artifact caches. Failure disables only the optional caller's tier. */
1598
+ export async function prepareBuildCacheRoot(root) {
1599
+ if (root === null)
1600
+ return null;
1601
+ try {
1602
+ await ensurePrivateCacheRoot(root, process.env["SCRIPTC_CACHE_DIR"] === undefined);
1603
+ return root;
1604
+ }
1605
+ catch {
1606
+ return null;
1607
+ }
1608
+ }
1609
+ /** Register a successful compiler-level cache write with the shared bounded
1610
+ * LRU policy. */
1611
+ export async function pruneBuildCache(root) {
1612
+ if (root !== null)
1613
+ await pruneCache(root).catch(() => undefined);
1614
+ }
1524
1615
  function cacheRootDir() {
1525
1616
  return resolveBuildCacheRoot();
1526
1617
  }