[clang] [compiler-rt] [llvm] [AIX] Implement the ifunc attribute. (PR #153049)
Wael Yehia via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 7 15:41:33 PDT 2025
================
@@ -0,0 +1,116 @@
+//===-- PPCPrepareIFuncsOnAIX.cpp - Prepare for ifunc lowering in codegen ===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass generates...
+//
+//===----------------------------------------------------------------------===//
+
+#include "PPC.h"
+#include "PPCSubtarget.h"
+#include "PPCTargetMachine.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Module.h"
+#include <cassert>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "ppc-prep-ifunc-aix"
+
+STATISTIC(NumIFuncs, "Number of IFuncs prepared");
+
+namespace {
+class PPCPrepareIFuncsOnAIX : public ModulePass {
+public:
+ static char ID;
+
+ PPCPrepareIFuncsOnAIX() : ModulePass(ID) {}
+
+ bool runOnModule(Module &M) override;
+
+ StringRef getPassName() const override {
+ return "PPC Prepare for AIX IFunc lowering";
+ }
+};
+} // namespace
+
+char PPCPrepareIFuncsOnAIX::ID = 0;
+
+INITIALIZE_PASS(PPCPrepareIFuncsOnAIX, DEBUG_TYPE,
+ "PPC Prepare for AIX IFunc lowering", false, false)
+
+ModulePass *llvm::createPPCPrepareIFuncsOnAIXPass() {
+ return new PPCPrepareIFuncsOnAIX();
+}
+
+// For each ifunc `foo` with a resolver `foo_resolver`, create a global variable
+// `__update_foo` in the `ifunc_sec` section, representing the pair:
+// { ptr @foo, ptr @foo_resolver }
+// The compiler arranges for the constructor function `__init_ifuncs` to be
+// included on the link step. The constructor walks the `ifunc_sec` section,
+// calling the resolver function and storing the result in foo's descriptor.
+// On AIX, the address of a function is the address of its descriptor, so the
+// constructor accesses foo's descriptor from the first field of the pair.
+//
+// Since the global `__update_foo` is unreferenced, it's liveness needs to be
+// associated to the liveness of ifunc `foo`
+//
+bool PPCPrepareIFuncsOnAIX::runOnModule(Module &M) {
+ if (M.ifuncs().empty())
+ return false;
+
+ const DataLayout &DL = M.getDataLayout();
+ LLVMContext &Ctx = M.getContext();
+ auto *PtrTy = PointerType::getUnqual(Ctx);
+ StringRef IFuncUpdatePrefix = "__update_";
+ StringRef IFuncUpdateSectionName = "ifunc_sec";
+ StructType *IFuncPairType = StructType::get(PtrTy, PtrTy);
+
+ StringRef IFuncConstructorName = "__init_ifuncs";
+ auto *IFuncConstructorFnType =
+ FunctionType::get(Type::getVoidTy(Ctx), {}, /*isVarArg=*/false);
+ auto *IFuncConstructorDecl =
+ Function::Create(IFuncConstructorFnType, GlobalValue::ExternalLinkage,
+ IFuncConstructorName, M);
+
+ for (GlobalIFunc &IFunc : M.ifuncs()) {
+ NumIFuncs++;
+ LLVM_DEBUG(dbgs() << "doing ifunc " << IFunc.getName() << "\n");
----------------
w2yehia wrote:
not super important, so i'll use "expanding".
https://github.com/llvm/llvm-project/pull/153049
More information about the cfe-commits
mailing list