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

>From b74f2c98947ad79d6b5012c734ce1719d8cb4bb7 Mon Sep 17 00:00:00 2001
From: Shivarama Rao <[email protected]>
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 flang generated ELF x86 and AArch64, and the 
default
remains PLT.

Assisted by Cursor in generating testcases.
---
 clang/include/clang/Options/Options.td        |  6 ++--
 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        |  9 ++++++
 flang/test/Driver/fno-plt.f90                 | 21 +++++++++++++
 flang/test/Integration/fno-plt-ir.ll          | 31 +++++++++++++++++++
 flang/test/Integration/fno-plt.f90            | 27 ++++++++++++++++
 9 files changed, 105 insertions(+), 3 deletions(-)
 create mode 100644 flang/test/Driver/fno-plt.f90
 create mode 100644 flang/test/Integration/fno-plt-ir.ll
 create mode 100644 flang/test/Integration/fno-plt.f90

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index b760c3a1213460..f9aa5a456a09bd 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],
-          "Use GOT indirection instead of PLT to make external function calls 
(x86 only)">,
-  PosFlag<SetFalse>>;
+  NegFlag<SetTrue, [], [ClangOption, CC1Option, FlangOption, FC1Option],
+          "Use GOT indirection instead of PLT to make external function calls 
(x86 and AArch64 only)">,
+  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..b535b079d2fea9 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -873,6 +873,15 @@ void CodeGenAction::generateLLVMIR() {
                                 opts.CodeObjectVersion);
     }
   }
+
+  // Add NonLazyBind attribute to function declarations when -fno-plt is used.
+  // Also set the RtLibUseGOT module flag so compiler-rt calls use the GOT.
+  if (opts.NoPLT) {
+    llvmModule->setRtLibUseGOT();
+    for (llvm::Function &func : *llvmModule)
+      if (func.isDeclaration() && !func.isIntrinsic())
+        func.addFnAttr(llvm::Attribute::NonLazyBind);
+  }
 }
 
 static std::unique_ptr<llvm::raw_pwrite_stream>
diff --git a/flang/test/Driver/fno-plt.f90 b/flang/test/Driver/fno-plt.f90
new file mode 100644
index 00000000000000..1b09fdd1a34ebd
--- /dev/null
+++ b/flang/test/Driver/fno-plt.f90
@@ -0,0 +1,21 @@
+! Test -f[no-]plt driver forwarding to flang -fc1.
+! 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.
+
+! 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 -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 -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
+
+! FC1: "-fc1"
+! DRIVER-NOPLT-SAME: "-fno-plt"
+! DRIVER-PLT-NOT: "-fno-plt"
+! UNUSED: warning: argument unused during compilation: '-fno-plt'
+! UNUSED-NOT: "-fno-plt"
+
+end program
diff --git a/flang/test/Integration/fno-plt-ir.ll 
b/flang/test/Integration/fno-plt-ir.ll
new file mode 100644
index 00000000000000..c26da2419499a7
--- /dev/null
+++ b/flang/test/Integration/fno-plt-ir.ll
@@ -0,0 +1,31 @@
+;===----------------------------------------------------------------------===;
+; This directory can be used to add Integration tests involving multiple
+; stages of the compiler (for eg. from Fortran to LLVM IR). It should not
+; contain executable tests. We should only add tests here sparingly and only
+; if there is no other way to test. Repeat this message in each test that is
+; added to this directory and sub-directories.
+;===----------------------------------------------------------------------===;
+
+; -fno-plt must not rewrite a loaded LLVM IR file. Clang leaves -x ir
+; input unchanged, and Flang applies the flag only while lowering Fortran.
+; -emit-llvm is required to check that the loaded module is not modified.
+
+; RUN: %flang_fc1 -x ir -emit-llvm -fno-plt -o - %s | FileCheck %s
+
+; The loaded functions are still emitted, and neither nonlazybind nor the
+; RtLibUseGOT module flag is added anywhere in the output.
+; CHECK-NOT: nonlazybind
+; CHECK-NOT: RtLibUseGOT
+; CHECK: define void @foo()
+; CHECK-NOT: nonlazybind
+; CHECK-NOT: RtLibUseGOT
+; CHECK: declare void @bar()
+; CHECK-NOT: nonlazybind
+; CHECK-NOT: RtLibUseGOT
+
+define void @foo() {
+  call void @bar()
+  ret void
+}
+
+declare void @bar()
diff --git a/flang/test/Integration/fno-plt.f90 
b/flang/test/Integration/fno-plt.f90
new file mode 100644
index 00000000000000..d0d8233ed1a409
--- /dev/null
+++ b/flang/test/Integration/fno-plt.f90
@@ -0,0 +1,27 @@
+!===----------------------------------------------------------------------===!
+! This directory can be used to add Integration tests involving multiple
+! stages of the compiler (for eg. from Fortran to LLVM IR). It should not
+! contain executable tests. We should only add tests here sparingly and only
+! if there is no other way to test. Repeat this message in each test that is
+! added to this directory and sub-directories.
+!===----------------------------------------------------------------------===!
+
+! nonlazybind and the RtLibUseGOT module flag are applied to the LLVM module
+! after FIR is translated, so -emit-hlfir and -emit-fir cannot observe them.
+! -fno-plt marks an external procedure nonlazybind and requests GOT for
+! compiler-rt. A procedure defined in this file is left unchanged. The
+! default does neither.
+
+! RUN: %flang_fc1 -emit-llvm -fno-plt -o - %s | FileCheck %s 
--check-prefix=NOPLT
+! RUN: %flang_fc1 -emit-llvm -o - %s | FileCheck %s --check-prefix=PLT
+
+subroutine test
+  call ext
+end subroutine
+
+! NOPLT: define void @test_()
+! NOPLT: declare void @ext_() #[[ATTR:[0-9]+]]
+! NOPLT: attributes #[[ATTR]] = { nonlazybind }
+! NOPLT: !"RtLibUseGOT"
+! PLT-NOT: nonlazybind
+! PLT-NOT: RtLibUseGOT

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to