From 242f5f3c7708e204f7558de87c02ee8b00e27d61 Mon Sep 17 00:00:00 2001 From: ASDAlexander77 Date: Tue, 20 Oct 2026 21:52:50 +0100 Subject: [PATCH 1/2] Borrow facts: name the symbol after the module's own file The JIT cache compiles each imported module through runMLIRPasses with isJit off, so the borrow-facts export ran for every import too, but its symbol was named from inputFilename - the main program. Every cached import then defined the same __tsborrow_
_, and the JIT failed to add the second one with a duplicate definition. Take the name from the module's main source buffer instead; for an --emit=obj build that is the same canonical path, so its symbol is unchanged. Co-Authored-By: Claude Opus 5.5 --- tslang/tslang/transform.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tslang/tslang/transform.cpp b/tslang/tslang/transform.cpp index 407cde8c1..fbbea95d8 100644 --- a/tslang/tslang/transform.cpp +++ b/tslang/tslang/transform.cpp @@ -156,11 +156,19 @@ int runMLIRPasses(mlir::MLIRContext &context, llvm::SourceMgr &sourceMgr, mlir:: } // What this module promises importers about its parameters, whether or not it promotes - // anything itself. Nothing imports a JIT-run program. + // anything itself. Nothing imports a JIT-run program. Named after the module's own file, + // the main buffer, not inputFilename: the JIT cache compiles each imported module this + // way too, and each one's symbol has to be its own. if (!compileOptions.isJit && !noBorrowFactsExport) { + llvm::StringRef moduleFile = inputFilename; + if (sourceMgr.getNumBuffers() > 0 && inputFilename != "-") + { + moduleFile = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID())->getBufferIdentifier(); + } + pm.addPass(mlir::typescript::createBorrowFactsExportPass( - SHARED_LIB_BORROW_FACTS + typescript::moduleSymbolSuffix(inputFilename))); + SHARED_LIB_BORROW_FACTS + typescript::moduleSymbolSuffix(moduleFile))); } // Under every model, after own's inference: what it decides about a stack object's retains From 5618e46836a69cce93ab72a37abc6b48202825f0 Mon Sep 17 00:00:00 2001 From: ASDAlexander77 Date: Tue, 20 Oct 2026 22:38:11 +0100 Subject: [PATCH 2/2] Borrow facts: not exported from the modules the JIT cache compiles The JIT cache compiles each imported module with isJit off and jitCache on. Those objects are only ever loaded into the JIT, never linked, and the program run there drops imported facts (StackPromotionPass), so the facts they carried were never read. Co-Authored-By: Claude Opus 5.5 --- tslang/tslang/transform.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tslang/tslang/transform.cpp b/tslang/tslang/transform.cpp index fbbea95d8..cceb0ee47 100644 --- a/tslang/tslang/transform.cpp +++ b/tslang/tslang/transform.cpp @@ -156,10 +156,12 @@ int runMLIRPasses(mlir::MLIRContext &context, llvm::SourceMgr &sourceMgr, mlir:: } // What this module promises importers about its parameters, whether or not it promotes - // anything itself. Nothing imports a JIT-run program. Named after the module's own file, - // the main buffer, not inputFilename: the JIT cache compiles each imported module this - // way too, and each one's symbol has to be its own. - if (!compileOptions.isJit && !noBorrowFactsExport) + // anything itself. Nothing imports a JIT-run program, nor the modules the JIT cache + // compiles beside it (isJit off, jitCache on): their objects are only loaded into the + // JIT, never linked, and the program run there does not read facts from them + // (StackPromotionPass). Named after the module's own file, the main buffer, not + // inputFilename, so a symbol is never another module's. + if (!compileOptions.isJit && !compileOptions.jitCache && !noBorrowFactsExport) { llvm::StringRef moduleFile = inputFilename; if (sourceMgr.getNumBuffers() > 0 && inputFilename != "-")