Skip to content

Add -funique-source-file-identifier option. #142901

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 12 additions & 5 deletions clang/docs/UsersManual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2300,12 +2300,14 @@ are listed below.
.. option:: -f[no-]unique-source-file-names

When enabled, allows the compiler to assume that each object file
passed to the linker has been compiled using a unique source file
path. This is useful for reducing link times when doing ThinLTO
in combination with whole-program devirtualization or CFI.
passed to the linker has a unique identifier. The identifier for
an object file is either the source file path or the value of the
argument `-funique-source-file-identifier` if specified. This is
useful for reducing link times when doing ThinLTO in combination with
whole-program devirtualization or CFI.

The full source path passed to the compiler must be unique. This
means that, for example, the following is a usage error:
The full source path or identifier passed to the compiler must be
unique. This means that, for example, the following is a usage error:

.. code-block:: console

Expand All @@ -2327,6 +2329,11 @@ are listed below.
A misuse of this flag may result in a duplicate symbol error at
link time.

.. option:: -funique-source-file-identifier=IDENTIFIER

Used with `-funique-source-file-names` to specify a source file
identifier.

.. option:: -fforce-emit-vtables

In order to improve devirtualization, forces emitting of vtables even in
Expand Down
2 changes: 0 additions & 2 deletions clang/include/clang/Basic/CodeGenOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,6 @@ CODEGENOPT(SanitizeCfiICallNormalizeIntegers, 1, 0) ///< Normalize integer types
///< CFI icall function signatures
CODEGENOPT(SanitizeCfiCanonicalJumpTables, 1, 0) ///< Make jump table symbols canonical
///< instead of creating a local jump table.
CODEGENOPT(UniqueSourceFileNames, 1, 0) ///< Allow the compiler to assume that TUs
///< have unique source file names at link time
CODEGENOPT(SanitizeKcfiArity, 1, 0) ///< Embed arity in KCFI patchable function prefix
CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage
///< instrumentation.
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,10 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// -fsymbol-partition (see https://lld.llvm.org/Partitions.html).
std::string SymbolPartition;

/// If non-empty, allow the compiler to assume that the given source file
/// identifier is unique at link time.
std::string UniqueSourceFileIdentifier;

enum RemarkKind {
RK_Missing, // Remark argument not present on the command line.
RK_Enabled, // Remark enabled via '-Rgroup'.
Expand Down
16 changes: 9 additions & 7 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4204,13 +4204,15 @@ def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>,
def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>,
HelpText<"Do not process trigraph sequences">,
Visibility<[ClangOption, CC1Option]>;
defm unique_source_file_names: BoolOption<"f", "unique-source-file-names",
CodeGenOpts<"UniqueSourceFileNames">, DefaultFalse,
PosFlag<SetTrue, [], [CC1Option], "Allow">,
NegFlag<SetFalse, [], [], "Do not allow">,
BothFlags<[], [ClangOption], " the compiler to assume that each translation unit has a unique "
"source file name at link time">>,
Group<f_clang_Group>;
def funique_source_file_names: Flag<["-"], "funique-source-file-names">, Group<f_Group>,
HelpText<"Allow the compiler to assume that each translation unit has a unique "
"source file identifier (see -funique-source-file-identifier) at link time">;
def fno_unique_source_file_names: Flag<["-"], "fno-unique-source-file-names">;
def unique_source_file_identifier_EQ: Joined<["-"], "funique-source-file-identifier=">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Specify the source file identifier for -funique-source-file-names; "
"uses the source file path if not specified">,
MarshallingInfoString<CodeGenOpts<"UniqueSourceFileIdentifier">>;
def funsigned_bitfields : Flag<["-"], "funsigned-bitfields">, Group<f_Group>;
def funsigned_char : Flag<["-"], "funsigned-char">, Group<f_Group>;
def fno_unsigned_char : Flag<["-"], "fno-unsigned-char">;
Expand Down
9 changes: 7 additions & 2 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1146,8 +1146,13 @@ void CodeGenModule::Release() {
1);
}

if (CodeGenOpts.UniqueSourceFileNames) {
getModule().addModuleFlag(llvm::Module::Max, "Unique Source File Names", 1);
if (!CodeGenOpts.UniqueSourceFileIdentifier.empty()) {
getModule().addModuleFlag(
llvm::Module::Append, "Unique Source File Identifier",
llvm::MDTuple::get(
TheModule.getContext(),
llvm::MDString::get(TheModule.getContext(),
CodeGenOpts.UniqueSourceFileIdentifier)));
}

if (LangOpts.Sanitize.has(SanitizerKind::KCFI)) {
Expand Down
10 changes: 8 additions & 2 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7740,8 +7740,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.addOptInFlag(CmdArgs, options::OPT_fexperimental_late_parse_attributes,
options::OPT_fno_experimental_late_parse_attributes);

Args.addOptInFlag(CmdArgs, options::OPT_funique_source_file_names,
options::OPT_fno_unique_source_file_names);
if (Args.hasFlag(options::OPT_funique_source_file_names,
options::OPT_fno_unique_source_file_names, false)) {
if (Arg *A = Args.getLastArg(options::OPT_unique_source_file_identifier_EQ))
A->render(Args, CmdArgs);
else
CmdArgs.push_back(Args.MakeArgString(
Twine("-funique-source-file-identifier=") + Input.getBaseInput()));
}

// Setup statistics file output.
SmallString<128> StatsFile = getStatsFileName(Args, Output, Input, D);
Expand Down
5 changes: 3 additions & 2 deletions clang/test/CodeGen/unique-source-file-names.c
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
// RUN: %clang_cc1 -funique-source-file-names -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
// CHECK: !{i32 7, !"Unique Source File Names", i32 1}
// RUN: %clang_cc1 -funique-source-file-identifier=foo -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
// CHECK: !{i32 5, !"Unique Source File Identifier", ![[MD:[0-9]*]]}
// CHECK: ![[MD]] = !{!"foo"}
12 changes: 9 additions & 3 deletions clang/test/Driver/unique-source-file-names.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
// RUN: %clang -funique-source-file-names -### %s 2> %t
// RUN: FileCheck < %t %s
// RUN: FileCheck --check-prefix=SRC < %t %s

// CHECK: "-cc1"
// CHECK: "-funique-source-file-names"
// SRC: "-cc1"
// SRC: "-funique-source-file-identifier={{.*}}unique-source-file-names.c"

// RUN: %clang -funique-source-file-names -funique-source-file-identifier=foo -### %s 2> %t
// RUN: FileCheck --check-prefix=ID < %t %s

// ID: "-cc1"
// ID: "-funique-source-file-identifier=foo"
10 changes: 6 additions & 4 deletions llvm/lib/Transforms/Utils/ModuleUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/xxhash.h"
Expand Down Expand Up @@ -346,10 +347,11 @@ void llvm::filterDeadComdatFunctions(
std::string llvm::getUniqueModuleId(Module *M) {
MD5 Md5;

auto *UniqueSourceFileNames = mdconst::extract_or_null<ConstantInt>(
M->getModuleFlag("Unique Source File Names"));
if (UniqueSourceFileNames && UniqueSourceFileNames->getZExtValue()) {
Md5.update(M->getSourceFileName());
auto *UniqueSourceFileIdentifier = dyn_cast_or_null<MDNode>(
M->getModuleFlag("Unique Source File Identifier"));
if (UniqueSourceFileIdentifier) {
Md5.update(
cast<MDString>(UniqueSourceFileIdentifier->getOperand(0))->getString());
} else {
bool ExportsSymbols = false;
for (auto &GV : M->global_values()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ define internal void @f() {
!0 = !{i32 0, !"typeid"}

!llvm.module.flags = !{!1}
!1 = !{i32 1, !"Unique Source File Names", i32 1}
!1 = !{i32 5, !"Unique Source File Identifier", !2}
!2 = !{!"unique-source-file-names.c"}
Loading