================ @@ -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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
