- Notifications
You must be signed in to change notification settings - Fork14.5k
[Clang][Driver] Expose relocation model as multilib flags#149132
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Conversation
If a multilib collection contains libraries built for differentmethods of accessing global data (via absolute address, or via a GOTin -fPIC style, or as an offset from a fixed register in Arm -frwpistyle), then `multilib.yaml` will need to know which relocation modelan application is using in order to select the right library.Even if a multilib collection only supports one relocation model, it'sstill useful for `multilib.yaml` to be able to tell if the user hasselected the right one, so as to give a useful error message if theyhaven't, instead of silently selecting a library that won't work.In this commit we determine the PIC / ROPI / RWPI status using theexisting logic in `ParsePICArgs`, and translate it back into acanonical set of multilib selection flags.
@llvm/pr-subscribers-clang Author: Simon Tatham (statham-arm) ChangesIf 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 Even if a multilib collection only supports one relocation model, it's still useful for In this commit we determine the PIC / ROPI / RWPI status using the existing logic in Full diff:https://github.com/llvm/llvm-project/pull/149132.diff 2 Files Affected:
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cppindex 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.cindex 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 |
@llvm/pr-subscribers-clang-driver Author: Simon Tatham (statham-arm) ChangesIf 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 Even if a multilib collection only supports one relocation model, it's still useful for In this commit we determine the PIC / ROPI / RWPI status using the existing logic in Full diff:https://github.com/llvm/llvm-project/pull/149132.diff 2 Files Affected:
diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cppindex 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.cindex 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 |
github-actionsbot commentedJul 16, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
✅ With the latest revision this PR passed the C/C++ code formatter. |
Note to reviewers: the thing I'm most uncertain of in this patch is whether I'm using the right strategy for finding out the information about relocation model.
But I'm notvery confident of what an "effective triple" is at all, and I don't know for sure that it's right to call |
(Thanks to clang-format for pointing out the trailing space on thatline, which was there because I meant to type a word after it!)
clang/lib/Driver/ToolChain.cpp Outdated
// 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) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Is there any way to move this Arm-only segment intogetARMMultilibFlags
? In theory, that function handles everything that is only relevant to Arm. So it's a more natural place to host this segment here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Done. In my early drafts I had the whole thing ingetARMMultilibFlags
, but moved it out once I realised that PIC needed to be handled as well as ROPI/RWPI. I've kept the calculation of the relocation model in the top-level function, and just passed the answer down intogetARMMultilibFlags
where it can add the Arm-specific options.
Answering my own question: I had failed to spot that |
All the CHECK lines are checked in a single run of FileCheck, so theoptions they mention must appear in the same order that the flags areshown in the -print-multi-flags output, which is ASCII sorting order.
3ce06b8
intollvm:mainUh oh!
There was an error while loading.Please reload this page.
ATfE doesn't currently provide any library variants built for RWPI. Andif you link RWPI with non-RWPI code, nothing good will happen – theyhave incompatible ABIs. So we ought to give an error message rather thansilently choose an incompatible library.Usingllvm/llvm-project#149132 which allowedmultilib selection to be aware of the relocation model at all, thiscommit does the simplest possible thing: adds a catch-all error messagethat will trigger on _any_ use of `-frwpi`, and report that there's nosuitable library variant.(Another possibility would have been to add `-fno-rwpi` to the validitycriteria for each existing library, but that seemed less likely to givea good error message. It would allow RWPI variants to be present forsome cases but not all, but at the moment, we don't need that.)Since the error message works the same everywhere, I've just added onetest.
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.