@scriptc/compiler 0.0.26 → 0.0.27
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/dist/backend/cc.d.ts +19 -0
- package/dist/backend/cc.js +91 -6
- package/dist/backend/cc.js.map +1 -1
- package/dist/backend/emission/emitter.js +9 -2
- package/dist/backend/emission/emitter.js.map +1 -1
- package/dist/backend/llvm/emitter.js +12 -4
- package/dist/backend/llvm/emitter.js.map +1 -1
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -1
- package/dist/ir/nodes.d.ts +6 -0
- package/dist/ir/nodes.js.map +1 -1
- package/dist/library/profile.d.ts +11 -0
- package/dist/library/profile.js +74 -2
- package/dist/library/profile.js.map +1 -1
- package/package.json +2 -2
- package/surface-manifest.json +1 -1
package/dist/backend/cc.d.ts
CHANGED
|
@@ -248,6 +248,25 @@ export interface LibArchiveOptions {
|
|
|
248
248
|
* matching compileC's arbitrary-input safety boundary. */
|
|
249
249
|
cacheIdentity?: string;
|
|
250
250
|
sanitize?: boolean;
|
|
251
|
+
/** Multi-instance library mode (the profile's abi.localize_runtime): the
|
|
252
|
+
* external symbols to KEEP global — every other scriptc external
|
|
253
|
+
* definition in the archive (the runtime's internals, the program TU's
|
|
254
|
+
* mangled functions and globals, vendor objects) is demoted to a local
|
|
255
|
+
* symbol. Toolchain sanitizer ABI remains external as required,
|
|
256
|
+
* so N archives built under pairwise-distinct prefixes link into one
|
|
257
|
+
* process with no symbol collisions and no shared mutable runtime state.
|
|
258
|
+
* Undefined references (libc/libm, plus sanitizer ABI in instrumented
|
|
259
|
+
* builds) keep their global binding. Omitted = the classic archive,
|
|
260
|
+
* byte-for-byte. Host-native builds only. */
|
|
261
|
+
localizeSymbols?: readonly string[];
|
|
262
|
+
/** Thread-instanced state (the profile's abi.instance_per_thread): every
|
|
263
|
+
* TU of the archive compiles with -DSCR_THREAD_INSTANCES, moving the
|
|
264
|
+
* runtime units' mutable statics into thread-local storage (SCR_TL in
|
|
265
|
+
* scr_runtime.h) to match the program TU's thread-local globals — one
|
|
266
|
+
* complete instance per embedder thread. The define rides cflags, so
|
|
267
|
+
* every cache tier keys it automatically; omitted = the classic
|
|
268
|
+
* archive, byte-for-byte. */
|
|
269
|
+
threadInstances?: boolean;
|
|
251
270
|
/** IR-detected link gates (the compileC precedent, refusal-narrowed). */
|
|
252
271
|
regex?: boolean;
|
|
253
272
|
assert?: boolean;
|
package/dist/backend/cc.js
CHANGED
|
@@ -757,6 +757,7 @@ export async function compileLibArchive(opts) {
|
|
|
757
757
|
"-fno-strict-aliasing", // the emitted object model type-puns — see compileC's buildArgs
|
|
758
758
|
"-Wno-deprecated-declarations",
|
|
759
759
|
"-DSCR_LIB",
|
|
760
|
+
...(opts.threadInstances ? ["-DSCR_THREAD_INSTANCES"] : []),
|
|
760
761
|
...(opts.textDecoderLegacy ? ["-DSCR_TEXT_DECODER_LEGACY"] : []),
|
|
761
762
|
"-I", rtDir,
|
|
762
763
|
...(regex ? ["-I", vendorEngineDir()] : []),
|
|
@@ -815,7 +816,12 @@ export async function compileLibArchive(opts) {
|
|
|
815
816
|
}
|
|
816
817
|
}
|
|
817
818
|
const vendorBuildIdentity = await currentVendorCacheBuildIdentity(driver, `${toolchainEnv}\0${implicitToolchain ?? "<uncached>"}`);
|
|
818
|
-
|
|
819
|
+
// Runtime-localized archives skip the completed-archive tier: their bytes
|
|
820
|
+
// additionally depend on the host's ld/objcopy identities, which the
|
|
821
|
+
// archive key does not fingerprint. The runtime-object tier still serves
|
|
822
|
+
// them (localization consumes the same per-flavor objects).
|
|
823
|
+
const cacheCompleteArchive = opts.localizeSymbols === undefined &&
|
|
824
|
+
root !== null && await archiverSupportsPersistentCache(arArgv, driver);
|
|
819
825
|
let cachedArchive = null;
|
|
820
826
|
let compilerVersion = "";
|
|
821
827
|
let archiverVersion = "";
|
|
@@ -968,17 +974,29 @@ export async function compileLibArchive(opts) {
|
|
|
968
974
|
}
|
|
969
975
|
}
|
|
970
976
|
const objects = [programObject, ...runtimeObjects, ...lreObjects, ...zlibObjects];
|
|
971
|
-
//
|
|
972
|
-
//
|
|
973
|
-
//
|
|
974
|
-
const
|
|
977
|
+
// Multi-instance library mode: the archive's one member becomes the
|
|
978
|
+
// combined, symbol-localized object (cached vendor/runtime objects
|
|
979
|
+
// are read-only inputs here — the combine step never mutates them).
|
|
980
|
+
const archiveMembers = opts.localizeSymbols === undefined
|
|
981
|
+
? objects
|
|
982
|
+
: [
|
|
983
|
+
await localizeLibraryObjects(driver, arArgv, buildDir, programObject, [...runtimeObjects, ...lreObjects, ...zlibObjects], opts.localizeSymbols, stem),
|
|
984
|
+
];
|
|
985
|
+
// A cacheable or runtime-localized build owns a private archive from
|
|
986
|
+
// `ar` through publication. Localized archives deliberately bypass the
|
|
987
|
+
// completed-artifact cache, but still need atomic installation so two
|
|
988
|
+
// invocations sharing a caller-visible output cannot race `rm`/`ar` on
|
|
989
|
+
// that path.
|
|
990
|
+
const archiveOutput = cachedArchive === null && opts.localizeSymbols === undefined
|
|
991
|
+
? opts.outPath
|
|
992
|
+
: join(buildDir, "artifact.lib.a");
|
|
975
993
|
await rm(archiveOutput, { force: true }); // `ar r` would append into a stale archive
|
|
976
994
|
await mkdir(dirname(archiveOutput), { recursive: true });
|
|
977
995
|
await execFileAsync(arArgv[0] ?? "ar", [
|
|
978
996
|
...arArgv.slice(1),
|
|
979
997
|
"rcs",
|
|
980
998
|
archiveOutput,
|
|
981
|
-
...
|
|
999
|
+
...archiveMembers,
|
|
982
1000
|
]);
|
|
983
1001
|
if (archiveOutput !== opts.outPath)
|
|
984
1002
|
await installArtifact(archiveOutput, opts.outPath);
|
|
@@ -1029,6 +1047,73 @@ export async function compileLibArchive(opts) {
|
|
|
1029
1047
|
if (root !== null)
|
|
1030
1048
|
await pruneCache(root).catch(() => undefined);
|
|
1031
1049
|
}
|
|
1050
|
+
/* Multi-instance library mode's localization step: combine the program
|
|
1051
|
+
* object with exactly the runtime/vendor members it reaches into ONE
|
|
1052
|
+
* relocatable object, then demote every scriptc external definition except
|
|
1053
|
+
* the profile-declared symbols to a local symbol. The internals are not
|
|
1054
|
+
* renamed apart — they stop being visible to the embedder's linker at all,
|
|
1055
|
+
* so a second archive built under a different prefix brings its own private
|
|
1056
|
+
* copy of the whole runtime (allocator, collector, arena, panic sink) into
|
|
1057
|
+
* the same process. Undefined references (libc/libm, plus sanitizer ABI in
|
|
1058
|
+
* instrumented builds) keep their global binding: the C library and
|
|
1059
|
+
* sanitizer are the embedder's, shared by design.
|
|
1060
|
+
*
|
|
1061
|
+
* Member selection matters: a classic archive's unused members (and their
|
|
1062
|
+
* undefined references to units library mode excludes, like the
|
|
1063
|
+
* fs-promises unit's fiber symbols) never reach an embedder's link. A
|
|
1064
|
+
* blind merge of every object would carry those references into the one
|
|
1065
|
+
* combined member. Staging the support objects into an intermediate
|
|
1066
|
+
* archive keeps the linker's own member semantics: `ld -r` pulls only the
|
|
1067
|
+
* members the program object transitively needs.
|
|
1068
|
+
*
|
|
1069
|
+
* darwin — one ld64 invocation: -r merges program + needed members,
|
|
1070
|
+
* -exported_symbols_list demotes every unlisted global to
|
|
1071
|
+
* private extern, and -r without -keep_private_externs writes
|
|
1072
|
+
* private externs out as non-external symbols. Apple ASan's
|
|
1073
|
+
* image-registration COMMON remains shared so the final Mach-O
|
|
1074
|
+
* image registers its globals once.
|
|
1075
|
+
* linux — ld -r merges with --force-group-allocation (ASan's
|
|
1076
|
+
* instrumented globals ride ELF section groups whose signatures
|
|
1077
|
+
* repeat across archives sharing runtime objects; resolving the
|
|
1078
|
+
* groups into the combined member keeps a later multi-archive
|
|
1079
|
+
* link from discarding one archive's copies), then binutils
|
|
1080
|
+
* objcopy --keep-global-symbols localizes every other DEFINED
|
|
1081
|
+
* global (objcopy leaves undefined symbols global by its own
|
|
1082
|
+
* rule).
|
|
1083
|
+
*
|
|
1084
|
+
* Host-native only: compileLibrary refuses localization for cross targets
|
|
1085
|
+
* before emission (this step runs the host's ld/objcopy over host-format
|
|
1086
|
+
* objects). */
|
|
1087
|
+
async function localizeLibraryObjects(driver, arArgv, buildDir, programObject, supportObjects, keepSymbols, stem) {
|
|
1088
|
+
const platform = targetPlatform(driver);
|
|
1089
|
+
const combined = join(buildDir, `${stem}.localized.o`);
|
|
1090
|
+
const staging = join(buildDir, `${stem}.localize-staging.a`);
|
|
1091
|
+
const keepFile = join(buildDir, "localize-keep.syms");
|
|
1092
|
+
const run = async (argv) => {
|
|
1093
|
+
try {
|
|
1094
|
+
await execFileAsync(argv[0], [...argv.slice(1)]);
|
|
1095
|
+
}
|
|
1096
|
+
catch (err) {
|
|
1097
|
+
const stderr = err.stderr ?? String(err);
|
|
1098
|
+
throw new Error(`${argv[0]} failed while localizing the library archive's runtime symbols (abi.localize_runtime).\n` +
|
|
1099
|
+
`Runtime symbol localization needs the host toolchain's ${platform === "darwin" ? "ld" : "ld and objcopy"} beside the C compiler.\n\n${stderr}`);
|
|
1100
|
+
}
|
|
1101
|
+
};
|
|
1102
|
+
await run([arArgv[0] ?? "ar", ...arArgv.slice(1), "rcs", staging, ...supportObjects]);
|
|
1103
|
+
if (platform === "darwin") {
|
|
1104
|
+
await writeFile(keepFile, keepSymbols.map((s) => `_${s}\n`).join(""));
|
|
1105
|
+
await run(["ld", "-r", programObject, staging, "-o", combined, "-exported_symbols_list", keepFile]);
|
|
1106
|
+
}
|
|
1107
|
+
else if (platform === "linux") {
|
|
1108
|
+
await writeFile(keepFile, keepSymbols.map((s) => `${s}\n`).join(""));
|
|
1109
|
+
await run(["ld", "-r", "--force-group-allocation", programObject, staging, "-o", combined]);
|
|
1110
|
+
await run(["objcopy", `--keep-global-symbols=${keepFile}`, combined]);
|
|
1111
|
+
}
|
|
1112
|
+
else {
|
|
1113
|
+
throw new Error(`runtime symbol localization (abi.localize_runtime) supports darwin and linux host builds; this build targets ${platform}`);
|
|
1114
|
+
}
|
|
1115
|
+
return combined;
|
|
1116
|
+
}
|
|
1032
1117
|
/* -------------------------- persistent build cache ---------------------------
|
|
1033
1118
|
* Content-addressed caches that let repeat builds of unchanged programs skip
|
|
1034
1119
|
* payload code generation/linking — the test lanes' dominant cost. Executable
|