//===-- 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 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 = cast( M.getOrInsertFunction(IFuncConstructorName, IFuncConstructorFnType) .getCallee()); for (GlobalIFunc &IFunc : M.ifuncs()) { NumIFuncs++; LLVM_DEBUG(dbgs() << "expanding ifunc " << IFunc.getName() << "\n"); // @__update_foo = private global { ptr @foo, ptr @foo_resolver }, // section "ifunc_sec" std::string Name = (Twine(IFuncUpdatePrefix) + IFunc.getName()).str(); auto *GV = new GlobalVariable(M, IFuncPairType, /*isConstant*/ false, GlobalValue::PrivateLinkage, nullptr, Name); GV->setAlignment(DL.getPointerPrefAlignment()); GV->setSection(IFuncUpdateSectionName); // Note that on AIX, the address of a function is the address of it's // function descriptor, which is what these two values end up being // in assembly. Constant *InitVals[] = {&IFunc, IFunc.getResolver()}; GV->setInitializer(ConstantStruct::get(IFuncPairType, InitVals)); // Liveness of __update_foo is dependent on liveness of ifunc foo. IFunc.setMetadata(LLVMContext::MD_implicit_ref, MDNode::get(Ctx, ValueAsMetadata::get(GV))); // An implicit.ref creates linkage dependency, so make function foo require // the constructor that calls each ifunc's resolver and saves the result in // the ifunc's function descriptor. IFunc.addMetadata( LLVMContext::MD_implicit_ref, *MDNode::get(Ctx, ValueAsMetadata::get(IFuncConstructorDecl))); } return true; }