| //===-- 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 "llvm/ADT/Statistic.h" | |
| #include "llvm/Analysis/TargetTransformInfo.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 = cast<Function>( | |
| 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; | |
| } |