[clang] [Clang][Driver] Expose relocation model as multilib flags (PR #149132)
Simon Tatham via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 17 05:54:12 PDT 2025
https://github.com/statham-arm updated https://github.com/llvm/llvm-project/pull/149132
>From c45a5196d44b4cee469d0a366ff8489227e2566f Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Mon, 14 Jul 2025 13:55:19 +0100
Subject: [PATCH 1/4] [Clang][Driver] Expose relocation model as multilib flags
If a multilib collection contains libraries built for different
methods of accessing global data (via absolute address, or via a GOT
in -fPIC style, or as an offset from a fixed register in Arm -frwpi
style), then `multilib.yaml` will need to know which relocation model
an application is using in order to select the right library.
Even if a multilib collection only supports one relocation model, it's
still useful for `multilib.yaml` to be able to tell if the user has
selected the right one, so as to give a useful error message if they
haven't, instead of silently selecting a library that won't work.
In this commit we determine the PIC / ROPI / RWPI status using the
existing logic in `ParsePICArgs`, and translate it back into a
canonical set of multilib selection flags.
---
clang/lib/Driver/ToolChain.cpp | 37 +++++++++++++++++++
.../test/Driver/print-multi-selection-flags.c | 19 ++++++++++
2 files changed, 56 insertions(+)
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 3f9b808b2722e..5738c0aa9b1d2 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -343,6 +343,7 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
std::vector<std::string> Result;
const llvm::Triple Triple(ComputeEffectiveClangTriple(Args));
Result.push_back("--target=" + Triple.str());
+ bool IsARM = false;
switch (Triple.getArch()) {
case llvm::Triple::aarch64:
@@ -355,6 +356,7 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
getARMMultilibFlags(D, Triple, Args, Result);
+ IsARM = true; // for ROPI/RWPI below
break;
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
@@ -376,6 +378,41 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
else
Result.push_back("-fexceptions");
+ // A difference of relocation model (absolutely addressed data, PIC, Arm
+ // ROPI/RWPI) is likely to change whether a particular multilib variant is
+ // compatible with a given link. Determine the relocation model of the
+ // current link, and add appropriate
+ {
+ RegisterEffectiveTriple TripleRAII(
+ *this, llvm::Triple(ComputeEffectiveClangTriple(Args)));
+
+ auto [RelocationModel, PICLevel, IsPIE] = tools::ParsePICArgs(*this, Args);
+
+ // ROPI and RWPI are only meaningful on Arm, so for other architectures, we
+ // expect never to find out they're enabled. But it seems confusing to add
+ // -fno-ropi and -fno-rwpi unconditionally to every other architecture's
+ // multilib flags, so instead we leave them out completely.
+ if (IsARM) {
+ if (RelocationModel == llvm::Reloc::ROPI ||
+ RelocationModel == llvm::Reloc::ROPI_RWPI)
+ Result.push_back("-fropi");
+ else
+ Result.push_back("-fno-ropi");
+
+ if (RelocationModel == llvm::Reloc::RWPI ||
+ RelocationModel == llvm::Reloc::ROPI_RWPI)
+ Result.push_back("-frwpi");
+ else
+ Result.push_back("-fno-rwpi");
+ }
+
+ if (RelocationModel == llvm::Reloc::PIC_)
+ Result.push_back(IsPIE ? (PICLevel > 1 ? "-fPIE" : "-fpie")
+ : (PICLevel > 1 ? "-fPIC" : "-fpic"));
+ else
+ Result.push_back("-fno-pic");
+ }
+
// Sort and remove duplicates.
std::sort(Result.begin(), Result.end());
Result.erase(llvm::unique(Result), Result.end());
diff --git a/clang/test/Driver/print-multi-selection-flags.c b/clang/test/Driver/print-multi-selection-flags.c
index 5f9383fbed8f4..1d794091970d3 100644
--- a/clang/test/Driver/print-multi-selection-flags.c
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -107,3 +107,22 @@
// CHECK-AARCH64-MULTILIB-CUSTOM-FLAG: --target=aarch64-unknown-none-eabi
// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=foo
// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=bar
+
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fropi | FileCheck --check-prefixes=CHECK-ROPI,CHECK-NO-RWPI,CHECK-NO-PIC %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -frwpi | FileCheck --check-prefixes=CHECK-RWPI,CHECK-NO-ROPI,CHECK-NO-PIC %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fropi -frwpi | FileCheck --check-prefixes=CHECK-ROPI,CHECK-RWPI,CHECK-NO-PIC %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fno-ropi -fno-rwpi | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-NO-PIC %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-NO-PIC %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fpic | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-PIC1 %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fPIC | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-PIC2 %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fpie | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-PIE1 %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fPIE | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-PIE2 %s
+// CHECK-ROPI: -fropi
+// CHECK-NO-ROPI: -fno-ropi
+// CHECK-RWPI: -frwpi
+// CHECK-NO-RWPI: -fno-rwpi
+// CHECK-PIC1: -fpic
+// CHECK-PIC2: -fPIC
+// CHECK-PIE1: -fpie
+// CHECK-PIE2: -fPIE
+// CHECK-NO-PIC: -fno-pic
>From 02eada87bcc21bd0e1503cb41361b666cc460d82 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Wed, 16 Jul 2025 17:20:10 +0100
Subject: [PATCH 2/4] Add missing end of sentence in comment
(Thanks to clang-format for pointing out the trailing space on that
line, which was there because I meant to type a word after it!)
---
clang/lib/Driver/ToolChain.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 5738c0aa9b1d2..72056bdd222eb 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -381,7 +381,7 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
// A difference of relocation model (absolutely addressed data, PIC, Arm
// ROPI/RWPI) is likely to change whether a particular multilib variant is
// compatible with a given link. Determine the relocation model of the
- // current link, and add appropriate
+ // current link, and add appropriate multilib flags.
{
RegisterEffectiveTriple TripleRAII(
*this, llvm::Triple(ComputeEffectiveClangTriple(Args)));
>From 877d7330d52ceed0b4ee2515878001fceef859d6 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 17 Jul 2025 12:43:59 +0100
Subject: [PATCH 3/4] Move ROPI/RWPI into the Arm-specific function
---
clang/lib/Driver/ToolChain.cpp | 75 +++++++++++++++-------------------
1 file changed, 34 insertions(+), 41 deletions(-)
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index 72056bdd222eb..481f575518b93 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -258,10 +258,10 @@ static void getAArch64MultilibFlags(const Driver &D,
processMultilibCustomFlags(Result, Args);
}
-static void getARMMultilibFlags(const Driver &D,
- const llvm::Triple &Triple,
- const llvm::opt::ArgList &Args,
- Multilib::flags_list &Result) {
+static void getARMMultilibFlags(const Driver &D, const llvm::Triple &Triple,
+ llvm::Reloc::Model RelocationModel,
+ const llvm::opt::ArgList &Args,
+ Multilib::flags_list &Result) {
std::vector<StringRef> Features;
llvm::ARM::FPUKind FPUKind = tools::arm::getARMTargetFeatures(
D, Triple, Args, Features, false /*ForAs*/, true /*ForMultilib*/);
@@ -304,6 +304,18 @@ static void getARMMultilibFlags(const Driver &D,
llvm_unreachable("Invalid float ABI");
}
+ if (RelocationModel == llvm::Reloc::ROPI ||
+ RelocationModel == llvm::Reloc::ROPI_RWPI)
+ Result.push_back("-fropi");
+ else
+ Result.push_back("-fno-ropi");
+
+ if (RelocationModel == llvm::Reloc::RWPI ||
+ RelocationModel == llvm::Reloc::ROPI_RWPI)
+ Result.push_back("-frwpi");
+ else
+ Result.push_back("-fno-rwpi");
+
const Arg *BranchProtectionArg =
Args.getLastArgNoClaim(options::OPT_mbranch_protection_EQ);
if (BranchProtectionArg) {
@@ -343,7 +355,18 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
std::vector<std::string> Result;
const llvm::Triple Triple(ComputeEffectiveClangTriple(Args));
Result.push_back("--target=" + Triple.str());
- bool IsARM = false;
+
+ // A difference of relocation model (absolutely addressed data, PIC, Arm
+ // ROPI/RWPI) is likely to change whether a particular multilib variant is
+ // compatible with a given link. Determine the relocation model of the
+ // current link, so as to add appropriate multilib flags.
+ llvm::Reloc::Model RelocationModel;
+ unsigned PICLevel;
+ bool IsPIE;
+ {
+ RegisterEffectiveTriple TripleRAII(*this, Triple);
+ std::tie(RelocationModel, PICLevel, IsPIE) = ParsePICArgs(*this, Args);
+ }
switch (Triple.getArch()) {
case llvm::Triple::aarch64:
@@ -355,8 +378,7 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
case llvm::Triple::armeb:
case llvm::Triple::thumb:
case llvm::Triple::thumbeb:
- getARMMultilibFlags(D, Triple, Args, Result);
- IsARM = true; // for ROPI/RWPI below
+ getARMMultilibFlags(D, Triple, RelocationModel, Args, Result);
break;
case llvm::Triple::riscv32:
case llvm::Triple::riscv64:
@@ -378,40 +400,11 @@ ToolChain::getMultilibFlags(const llvm::opt::ArgList &Args) const {
else
Result.push_back("-fexceptions");
- // A difference of relocation model (absolutely addressed data, PIC, Arm
- // ROPI/RWPI) is likely to change whether a particular multilib variant is
- // compatible with a given link. Determine the relocation model of the
- // current link, and add appropriate multilib flags.
- {
- RegisterEffectiveTriple TripleRAII(
- *this, llvm::Triple(ComputeEffectiveClangTriple(Args)));
-
- auto [RelocationModel, PICLevel, IsPIE] = tools::ParsePICArgs(*this, Args);
-
- // ROPI and RWPI are only meaningful on Arm, so for other architectures, we
- // expect never to find out they're enabled. But it seems confusing to add
- // -fno-ropi and -fno-rwpi unconditionally to every other architecture's
- // multilib flags, so instead we leave them out completely.
- if (IsARM) {
- if (RelocationModel == llvm::Reloc::ROPI ||
- RelocationModel == llvm::Reloc::ROPI_RWPI)
- Result.push_back("-fropi");
- else
- Result.push_back("-fno-ropi");
-
- if (RelocationModel == llvm::Reloc::RWPI ||
- RelocationModel == llvm::Reloc::ROPI_RWPI)
- Result.push_back("-frwpi");
- else
- Result.push_back("-fno-rwpi");
- }
-
- if (RelocationModel == llvm::Reloc::PIC_)
- Result.push_back(IsPIE ? (PICLevel > 1 ? "-fPIE" : "-fpie")
- : (PICLevel > 1 ? "-fPIC" : "-fpic"));
- else
- Result.push_back("-fno-pic");
- }
+ if (RelocationModel == llvm::Reloc::PIC_)
+ Result.push_back(IsPIE ? (PICLevel > 1 ? "-fPIE" : "-fpie")
+ : (PICLevel > 1 ? "-fPIC" : "-fpic"));
+ else
+ Result.push_back("-fno-pic");
// Sort and remove duplicates.
std::sort(Result.begin(), Result.end());
>From 2568c65829ec2ef3f7b4b8855b204838032e3633 Mon Sep 17 00:00:00 2001
From: Simon Tatham <simon.tatham at arm.com>
Date: Thu, 17 Jul 2025 13:51:45 +0100
Subject: [PATCH 4/4] Fix the test
All the CHECK lines are checked in a single run of FileCheck, so the
options they mention must appear in the same order that the flags are
shown in the -print-multi-flags output, which is ASCII sorting order.
---
clang/test/Driver/print-multi-selection-flags.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/clang/test/Driver/print-multi-selection-flags.c b/clang/test/Driver/print-multi-selection-flags.c
index 1d794091970d3..8cf8f04bb6b48 100644
--- a/clang/test/Driver/print-multi-selection-flags.c
+++ b/clang/test/Driver/print-multi-selection-flags.c
@@ -109,7 +109,7 @@
// CHECK-MULTILIB-CUSTOM-FLAG-DAG: -fmultilib-flag=bar
// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fropi | FileCheck --check-prefixes=CHECK-ROPI,CHECK-NO-RWPI,CHECK-NO-PIC %s
-// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -frwpi | FileCheck --check-prefixes=CHECK-RWPI,CHECK-NO-ROPI,CHECK-NO-PIC %s
+// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -frwpi | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-RWPI,CHECK-NO-PIC %s
// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fropi -frwpi | FileCheck --check-prefixes=CHECK-ROPI,CHECK-RWPI,CHECK-NO-PIC %s
// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fno-ropi -fno-rwpi | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-NO-PIC %s
// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-NO-PIC %s
@@ -117,12 +117,12 @@
// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fPIC | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-PIC2 %s
// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fpie | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-PIE1 %s
// RUN: %clang -multi-lib-config=%S/Inputs/multilib/empty.yaml -print-multi-flags-experimental --target=arm-none-eabi -march=armv7a -fPIE | FileCheck --check-prefixes=CHECK-NO-ROPI,CHECK-NO-RWPI,CHECK-PIE2 %s
-// CHECK-ROPI: -fropi
+// CHECK-PIC2: -fPIC
+// CHECK-PIE2: -fPIE
+// CHECK-NO-PIC: -fno-pic
// CHECK-NO-ROPI: -fno-ropi
-// CHECK-RWPI: -frwpi
// CHECK-NO-RWPI: -fno-rwpi
// CHECK-PIC1: -fpic
-// CHECK-PIC2: -fPIC
// CHECK-PIE1: -fpie
-// CHECK-PIE2: -fPIE
-// CHECK-NO-PIC: -fno-pic
+// CHECK-ROPI: -fropi
+// CHECK-RWPI: -frwpi
More information about the cfe-commits
mailing list