From 7c770d08877c27a651c60625b8ddec745acb35b2 Mon Sep 17 00:00:00 2001 From: Chris Tate Date: Tue, 27 Oct 2026 03:30:15 -0500 Subject: [PATCH] Name the source file in empty split codegen parts When --split codegen keeps the module whole, the extra outputs are new empty modules, and their source file name defaulted to the module identifier: the path of the private copy of the LLVM input, which has a random name. That name reached each part's STT_FILE symbol, so two release builds of one program differed in .strtab. The empty parts now take the module's source file name, as the first part has it. --- native/llvm-codegen/src/emit.cpp | 2 ++ packages/compiler/test/native-partitions.test.ts | 10 ++++++++++ 2 files changed, 12 insertions(+) diff --git a/native/llvm-codegen/src/emit.cpp b/native/llvm-codegen/src/emit.cpp index 1ab0f6ecd..d3d868fae 100644 --- a/native/llvm-codegen/src/emit.cpp +++ b/native/llvm-codegen/src/emit.cpp @@ -1241,6 +1241,7 @@ emitSplitCodegen(const EmitOptions &Options, Module &M, TargetMachine &Machine, size_t Count = Options.Outputs.size(); std::optional Split = splitForCodegen(M, Count); std::string Identifier = M.getModuleIdentifier(); + std::string SourceFileName = M.getSourceFileName(); Triple TargetTriple = M.getTargetTriple(); DataLayout Layout = M.getDataLayout(); std::vector>> Temporaries(Count); @@ -1274,6 +1275,7 @@ emitSplitCodegen(const EmitOptions &Options, Module &M, TargetMachine &Machine, keepCodegenPart(*Part, Split->PartOf, I); } else { Part = std::make_unique(Identifier, Context); + Part->setSourceFileName(SourceFileName); Part->setTargetTriple(TargetTriple); Part->setDataLayout(Layout); } diff --git a/packages/compiler/test/native-partitions.test.ts b/packages/compiler/test/native-partitions.test.ts index c86a37aa4..18d0aa749 100644 --- a/packages/compiler/test/native-partitions.test.ts +++ b/packages/compiler/test/native-partitions.test.ts @@ -327,6 +327,16 @@ describe.runIf(helper !== null)("LLVM program partitions", () => { const first = await readFile(parts[0]!); const [single] = await emit(dir, source, { outputs: 1, optLevel: "2", name: "whole" }); expect(await readFile(single!)).toEqual(first); + // The empty parts name the source path, so they do not depend on the + // input's file name either. + const renamed = await emit(dir, source, { + outputs: 3, + optLevel: "2", + split: true, + name: "renamed", + }); + for (let index = 0; index < parts.length; index++) + expect(await readFile(renamed[index]!)).toEqual(await readFile(parts[index]!)); }); test("split code generation requires several optimized outputs and no cache", async () => {