[flang-commits] [clang] [flang] [Flang] [Driver] Add -fplt and -fno-plt options (PR #235622)

via flang-commits flang-commits at lists.llvm.org
Mon Oct 26 00:11:01 PDT 2026


https://github.com/shivaramaarao created https://github.com/llvm/llvm-project/pull/235622

The option is supported in clang and not in flang. This commit adds this support. -fno-plt makes external calls use GOT indirection instead of the PLT. The driver forwards it only for ELF x86 and AArch64, and the default remains PLT.

>From 4512e0804b7ba1831002f0e56507b6a0d1a85834 Mon Sep 17 00:00:00 2001
From: Shivarama Rao <shivarama.rao at amd.com>
Date: Mon, 26 Oct 2026 12:05:52 +0530
Subject: [PATCH] [Flang] [Driver] Add -fplt and -fno-plt options

The option is supported in clang and not in flang. This commit adds this
support. -fno-plt makes external calls use GOT indirection instead of the PLT.
The driver forwards it only for ELF x86 and AArch64, and the default
remains PLT.
---
 clang/include/clang/Options/Options.td        |  4 +-
 clang/lib/Driver/ToolChains/Flang.cpp         |  4 ++
 flang/docs/ReleaseNotes.md                    |  4 ++
 .../include/flang/Frontend/CodeGenOptions.def |  1 +
 flang/lib/Frontend/CompilerInvocation.cpp     |  5 +++
 flang/lib/Frontend/FrontendActions.cpp        | 12 ++++++
 flang/test/Driver/fno-plt.f90                 | 37 +++++++++++++++++++
 7 files changed, 65 insertions(+), 2 deletions(-)
 create mode 100644 flang/test/Driver/fno-plt.f90

diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index b760c3a1213460..98e6700082e0e1 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -4516,9 +4516,9 @@ def fno_direct_access_external_data : Flag<["-"], "fno-direct-access-external-da
   HelpText<"Use GOT indirection to reference external data symbols">;
 defm plt : BoolFOption<"plt",
   CodeGenOpts<"NoPLT">, DefaultFalse,
-  NegFlag<SetTrue, [], [ClangOption, CC1Option],
+  NegFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option],
           "Use GOT indirection instead of PLT to make external function calls (x86 only)">,
-  PosFlag<SetFalse>>;
+  PosFlag<SetFalse, [], [ClangOption, CC1Option, FlangOption, FC1Option]>>;
 defm ropi : BoolFOption<"ropi",
   LangOpts<"ROPI">, DefaultFalse,
   PosFlag<SetTrue, [], [ClangOption, FlangOption, CC1Option],
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 94b092e711be64..a4e0ed589b53e9 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -398,6 +398,10 @@ void Flang::addCodegenOptions(const ArgList &Args,
                      options::OPT_fno_optimize_sibling_calls);
 
   const llvm::Triple &Triple = getToolChain().getEffectiveTriple();
+  // Only ELF x86 and AArch64 use -fno-plt. The default is PLT,
+  // so only an explicit -fno-plt (last flag wins) is forwarded.
+  if (Triple.isOSBinFormatELF() && (Triple.isAArch64() || Triple.isX86()))
+    Args.addOptOutFlag(CmdArgs, options::OPT_fplt, options::OPT_fno_plt);
   addSeparateSectionFlags(Triple, Args, CmdArgs);
 
   if (Args.hasArg(options::OPT_fcoarray))
diff --git a/flang/docs/ReleaseNotes.md b/flang/docs/ReleaseNotes.md
index 147b15106b9146..b0e1624dcdeba3 100644
--- a/flang/docs/ReleaseNotes.md
+++ b/flang/docs/ReleaseNotes.md
@@ -163,6 +163,10 @@ page](https://llvm.org/releases/).
   equal the array's declared leading extent, so that the common case has a
   constant trip count.
 
+- Added `-fplt` and `-fno-plt`. `-fno-plt` makes external function
+  calls use GOT indirection instead of the PLT. The driver forwards
+  it for ELF x86 and AArch64. The default remains PLT.
+
 ## Windows Support
 
 ## Fortran Language Changes in Flang
diff --git a/flang/include/flang/Frontend/CodeGenOptions.def b/flang/include/flang/Frontend/CodeGenOptions.def
index 569a6aa289ca31..44e0528783b571 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.def
+++ b/flang/include/flang/Frontend/CodeGenOptions.def
@@ -33,6 +33,7 @@ ENUM_CODEGENOPT(ProfileUse, llvm::driver::ProfileInstrKind, 2, llvm::driver::Pro
 CODEGENOPT(InstrumentFunctions, 1, 0) ///< Set when -finstrument_functions is
                                       ///< enabled on the compile step.
 CODEGENOPT(DisableTailCalls, 1, 0) ///< Do not emit tail calls
+CODEGENOPT(NoPLT, 1, 0) ///< -fno-plt: use GOT indirection for external calls
 
 CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as
 
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 38e66aad693cbc..20564ad5abc131 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -393,6 +393,11 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
   if (args.hasArg(clang::options::OPT_fno_optimize_sibling_calls))
     opts.DisableTailCalls = 1;
 
+  // -fplt / -fno-plt. The driver forwards only -fno-plt, and only for ELF
+  // x86 and AArch64. Last flag wins if both reach the frontend.
+  opts.NoPLT = args.hasFlag(clang::options::OPT_fno_plt,
+                            clang::options::OPT_fplt, /*Default=*/false);
+
   // -fno-integrated-as: emit GNU Assembler compatible assembly.
   if (!args.hasFlag(clang::options::OPT_fintegrated_as,
                     clang::options::OPT_fno_integrated_as, true))
diff --git a/flang/lib/Frontend/FrontendActions.cpp b/flang/lib/Frontend/FrontendActions.cpp
index 9191f22b7024e8..0dd2d1dbafcee7 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -1438,6 +1438,18 @@ void CodeGenAction::executeAction() {
   llvmModule->setTargetTriple(theTriple);
   llvmModule->setDataLayout(theTriple.computeDataLayout(targetOpts.abi));
 
+  // -fno-plt: external calls use the GOT instead of the PLT. The module
+  // requests GOT for compiler-rt, and declarations that are not defined in
+  // this translation unit are marked nonlazybind.
+  if (codeGenOpts.NoPLT) {
+    llvmModule->setRtLibUseGOT();
+    for (llvm::Function &func : *llvmModule) {
+      if (!func.isDeclaration() || func.isIntrinsic())
+        continue;
+      func.addFnAttr(llvm::Attribute::NonLazyBind);
+    }
+  }
+
   // Link in builtin bitcode libraries
   if (!codeGenOpts.BuiltinBCLibs.empty())
     linkBuiltinBCLibs();
diff --git a/flang/test/Driver/fno-plt.f90 b/flang/test/Driver/fno-plt.f90
new file mode 100644
index 00000000000000..1e2503f41ce013
--- /dev/null
+++ b/flang/test/Driver/fno-plt.f90
@@ -0,0 +1,37 @@
+! Test -f[no-]plt.
+! The driver forwards -fno-plt only for ELF x86 and AArch64. The default is
+! PLT, so -fplt is not forwarded. Other targets warn that the flag is unused.
+! In codegen, -fno-plt marks external procedures nonlazybind and requests GOT
+! for compiler-rt. A procedure defined in this file is left unchanged.
+! The default, and -fplt after -fno-plt, do neither.
+
+! RUN: %flang -### --target=x86_64-unknown-linux-gnu -fno-plt %s 2>&1 | FileCheck %s --check-prefixes=FC1,DRIVER-NOPLT
+! RUN: %flang -### --target=aarch64-unknown-linux-gnu -fno-plt %s 2>&1 | FileCheck %s --check-prefixes=FC1,DRIVER-NOPLT
+! RUN: %flang -### --target=x86_64-unknown-linux-gnu -fplt -fno-plt %s 2>&1 | FileCheck %s --check-prefixes=FC1,DRIVER-NOPLT
+! RUN: %flang -### --target=x86_64-unknown-linux-gnu %s 2>&1 | FileCheck %s --check-prefixes=FC1,DRIVER-PLT
+! RUN: %flang -### --target=x86_64-unknown-linux-gnu -fplt %s 2>&1 | FileCheck %s --check-prefixes=FC1,DRIVER-PLT
+! RUN: %flang -### --target=x86_64-unknown-linux-gnu -fno-plt -fplt %s 2>&1 | FileCheck %s --check-prefixes=FC1,DRIVER-PLT
+! RUN: %flang -### --target=powerpc64le-unknown-linux-gnu -fno-plt %s 2>&1 | FileCheck %s --check-prefixes=UNUSED,DRIVER-PLT
+! RUN: %flang -### --target=aarch64-unknown-windows-msvc -fno-plt %s 2>&1 | FileCheck %s --check-prefixes=UNUSED,DRIVER-PLT
+! RUN: %flang -### --target=x86_64-unknown-windows-msvc -fno-plt %s 2>&1 | FileCheck %s --check-prefixes=UNUSED,DRIVER-PLT
+
+! RUN: %flang_fc1 -emit-llvm -fno-plt -o - %s | FileCheck %s --check-prefix=IR-NOPLT
+! RUN: %flang_fc1 -emit-llvm -o - %s | FileCheck %s --check-prefix=IR-PLT
+! RUN: %flang_fc1 -emit-llvm -fno-plt -fplt -o - %s | FileCheck %s --check-prefix=IR-PLT
+
+subroutine test
+  call ext
+end subroutine
+
+! FC1: "-fc1"
+! DRIVER-NOPLT-SAME: "-fno-plt"
+! DRIVER-PLT-NOT: "-fno-plt"
+! UNUSED: warning: argument unused during compilation: '-fno-plt'
+! UNUSED-NOT: "-fno-plt"
+
+! IR-NOPLT: define void @test_()
+! IR-NOPLT: declare void @ext_() #[[ATTR:[0-9]+]]
+! IR-NOPLT: attributes #[[ATTR]] = { nonlazybind }
+! IR-NOPLT: !"RtLibUseGOT"
+! IR-PLT-NOT: nonlazybind
+! IR-PLT-NOT: RtLibUseGOT



More information about the flang-commits mailing list