From c4bb1e6f552d71c3fdcdac2fd1f5e12ad7d82003 Mon Sep 17 00:00:00 2001
From: luofeng14 <luofeng13@huawei.com>
Date: Thu, 13 Mar 2025 19:34:49 +0800
Subject: [PATCH] [Huawei][AArch64] Fix -fno-plt to suppress PLT generation
Clang 17/19 -fno-plt fix: Aligns with GCC by suppressing PLT entries as expected.
Co-authored-by: Chen Zheng
---
llvm/lib/CodeGen/DwarfEHPrepare.cpp | 6 ++++
llvm/lib/Target/AArch64/AArch64Subtarget.cpp | 14 ++++++++
llvm/test/CodeGen/AArch64/fno-plt.cpp | 36 +++++++++++++++++++
.../Analysis/TargetLibraryInfoTest.cpp | 5 +++
4 files changed, 61 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/fno-plt.cpp
diff --git a/llvm/lib/CodeGen/DwarfEHPrepare.cpp b/llvm/lib/CodeGen/DwarfEHPrepare.cpp
index 32c94de7280c..d8882bd53ed6 100644
--- a/llvm/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/llvm/lib/CodeGen/DwarfEHPrepare.cpp
@@ -234,6 +234,12 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls() {
}
RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy);
+#if defined(BUILD_FOR_OPENEULER)
+ // If -fno-plt is enabled, add NonLazyBind for this library call.
+ if (F.getParent()->getRtLibUseGOT())
+ (cast<Function>(RewindFunction.getCallee()))->addFnAttr(Attribute::NonLazyBind);
+#endif
+
// Create the basic block where the _Unwind_Resume call will live.
if (ResumesLeft == 1) {
// Instead of creating a new BB and PHI node, just append the call to
diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp
index 538021ddb2fd..aa6527efbb17 100644
--- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp
+++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp
@@ -24,6 +24,9 @@
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineScheduler.h"
#include "llvm/IR/GlobalValue.h"
+#if defined(BUILD_FOR_OPENEULER)
+#include "llvm/IR/Module.h"
+#endif
#include "llvm/TargetParser/AArch64TargetParser.h"
using namespace llvm;
@@ -433,9 +436,20 @@ unsigned AArch64Subtarget::classifyGlobalFunctionReference(
// NonLazyBind goes via GOT unless we know it's available locally.
auto *F = dyn_cast<Function>(GV);
+#if defined(BUILD_FOR_OPENEULER)
+// Check if NonLazyBind should go via GOT:
+// 1. The target is not MachO, or MachO uses NonLazyBind.
+// 2. The function's parent module requires GOT for runtime library calls.
+// 3. The symbol is not assumed to be DSO-local.
+// 4. The symbol does not have local linkage.
+ if ((!isTargetMachO() || MachOUseNonLazyBind) && F &&
+ F->getParent()->getRtLibUseGOT() &&
+ !(TM.shouldAssumeDSOLocal(*GV->getParent(), GV) || GV->hasLocalLinkage()))
+#else
if ((!isTargetMachO() || MachOUseNonLazyBind) && F &&
F->hasFnAttribute(Attribute::NonLazyBind) &&
!TM.shouldAssumeDSOLocal(*GV->getParent(), GV))
+#endif
return AArch64II::MO_GOT;
if (getTargetTriple().isOSWindows()) {
diff --git a/llvm/test/CodeGen/AArch64/fno-plt.cpp b/llvm/test/CodeGen/AArch64/fno-plt.cpp
new file mode 100644
index 000000000000..619e5d1cc60e
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/fno-plt.cpp
@@ -0,0 +1,36 @@
+// REQUIRES: build_for_openeuler
+// RUN: clang -x c++ %s -shared -fno-plt -O2 -fno-inline -fPIC -o noplt.so
+// RUN: llvm-objdump -d noplt.so | FileCheck %s --check-prefix=CHECK-NO-PLT
+
+// RUN: clang -x c++ %s -shared -O0 -fPIC -o plt.so
+// RUN: llvm-objdump -d plt.so | FileCheck %s --check-prefix=CHECK-PLT
+
+// RUN: clang -x c++ %s -shared -O2 -fno-inline -fPIC -o plt.so
+// RUN: llvm-objdump -d plt.so | FileCheck %s --check-prefix=CHECK-PLT
+
+// CHECK-PLT: bar@plt
+// CHECK-PLT: bar1@plt
+// CHECK-NO-PLT-NOT: bar@plt
+// CHECK-NO-PLT-NOT: bar1@plt
+// CHECK-NO-PLT-NOT: bar2@plt
+
+__attribute__((optnone))
+void bar(int a) {
+ return;
+}
+
+__attribute__((optnone))
+extern void bar1(int);
+
+__attribute__((optnone))
+static void bar2(int a) {
+ return;
+}
+
+void foo(int a) {
+ bar(a);
+ bar1(a);
+ bar2(a);
+ return;
+}
+
diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
index b91c2617c507..dc8eb84469f4 100644
--- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
+++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp
@@ -412,6 +412,8 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
"declare i32 @fseeko64(%struct*, i64, i32)\n"
"declare i64 @ftello64(%struct*)\n"
+ "declare void @_Unwind_Resume(%struct*)\n"
+ "declare void @_ZSt9terminatev()\n"
"declare void @_ZdaPv(i8*)\n"
"declare void @_ZdaPvRKSt9nothrow_t(i8*, %struct*)\n"
"declare void @_ZdaPvSt11align_val_t(i8*, i64)\n"
@@ -478,7 +480,9 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
"declare void @\"??_V@YAXPAXI@Z\"(i8*, i32)\n"
// These other functions were derived from the .def C declaration.
+ "declare i8* @__cxa_allocate_exception(i64)\n"
"declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)\n"
+ "declare i8* @__cxa_begin_catch(i8*)\n"
"declare void @__cxa_guard_abort(%struct*)\n"
"declare i32 @__cxa_guard_acquire(%struct*)\n"
"declare void @__cxa_guard_release(%struct*)\n"
@@ -569,6 +573,7 @@ TEST_F(TargetLibraryInfoTest, ValidProto) {
"declare double @__cosh_finite(double)\n"
"declare float @__coshf_finite(float)\n"
"declare x86_fp80 @__coshl_finite(x86_fp80)\n"
+ "declare void @__cxa_throw(i8*, i8*, i8*)\n"
"declare double @__exp10_finite(double)\n"
"declare float @__exp10f_finite(float)\n"
"declare x86_fp80 @__exp10l_finite(x86_fp80)\n"
--
2.43.0