[clang] [Clang][Driver] Expose relocation model as multilib flags (PR #149132)

Simon Tatham via cfe-commits cfe-commits at lists.llvm.org
Wed Jul 16 09:16:14 PDT 2025


https://github.com/statham-arm created https://github.com/llvm/llvm-project/pull/149132

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.

>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] [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



More information about the cfe-commits mailing list