LLVM 23.0.0git
PPCPrepareIFuncsOnAIX.cpp
Go to the documentation of this file.
1//===-- PPCPrepareIFuncsOnAIX.cpp - Prepare for ifunc lowering in codegen ===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This pass generates...
10//
11//===----------------------------------------------------------------------===//
12
13#include "PPC.h"
14#include "PPCSubtarget.h"
15#include "PPCTargetMachine.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/Statistic.h"
21#include "llvm/IR/Module.h"
22#include <cassert>
23
24using namespace llvm;
25
26#define DEBUG_TYPE "ppc-prep-ifunc-aix"
27
28STATISTIC(NumIFuncs, "Number of IFuncs prepared");
29
30namespace {
31class PPCPrepareIFuncsOnAIX : public ModulePass {
32public:
33 static char ID;
34
35 PPCPrepareIFuncsOnAIX() : ModulePass(ID) {}
36
37 bool runOnModule(Module &M) override;
38
39 StringRef getPassName() const override {
40 return "PPC Prepare for AIX IFunc lowering";
41 }
42};
43} // namespace
44
45char PPCPrepareIFuncsOnAIX::ID = 0;
46
47INITIALIZE_PASS(PPCPrepareIFuncsOnAIX, DEBUG_TYPE,
48 "PPC Prepare for AIX IFunc lowering", false, false)
49
51 return new PPCPrepareIFuncsOnAIX();
52}
53
54// For each ifunc `foo` with a resolver `foo_resolver`, create a global variable
55// `__update_foo` in the `ifunc_sec` section, representing the pair:
56// { ptr @foo, ptr @foo_resolver }
57// The compiler arranges for the constructor function `__init_ifuncs` to be
58// included on the link step. The constructor walks the `ifunc_sec` section,
59// calling the resolver function and storing the result in foo's descriptor.
60// On AIX, the address of a function is the address of its descriptor, so the
61// constructor accesses foo's descriptor from the first field of the pair.
62//
63// Since the global `__update_foo` is unreferenced, it's liveness needs to be
64// associated to the liveness of ifunc `foo`
65//
66bool PPCPrepareIFuncsOnAIX::runOnModule(Module &M) {
67 if (M.ifuncs().empty())
68 return false;
69
70 const DataLayout &DL = M.getDataLayout();
71 LLVMContext &Ctx = M.getContext();
72 auto *PtrTy = PointerType::getUnqual(Ctx);
73 StringRef IFuncUpdatePrefix = "__update_";
74 StringRef IFuncUpdateSectionName = "__ifunc_sec";
75 StructType *IFuncPairType = StructType::get(PtrTy, PtrTy);
76
77 StringRef IFuncConstructorName = "__init_ifuncs";
78 auto *IFuncConstructorFnType =
79 FunctionType::get(Type::getVoidTy(Ctx), {}, /*isVarArg=*/false);
80 auto *IFuncConstructorDecl = cast<Function>(
81 M.getOrInsertFunction(IFuncConstructorName, IFuncConstructorFnType)
82 .getCallee());
83
84 for (GlobalIFunc &IFunc : M.ifuncs()) {
85 NumIFuncs++;
86 LLVM_DEBUG(dbgs() << "expanding ifunc " << IFunc.getName() << "\n");
87 // @__update_foo = private global { ptr @foo, ptr @foo_resolver },
88 // section "ifunc_sec"
89 std::string Name = (Twine(IFuncUpdatePrefix) + IFunc.getName()).str();
90 auto *GV = new GlobalVariable(M, IFuncPairType, /*isConstant*/ false,
91 GlobalValue::PrivateLinkage, nullptr, Name);
92 GV->setAlignment(DL.getPointerPrefAlignment());
93 GV->setSection(IFuncUpdateSectionName);
94
95 // Note that on AIX, the address of a function is the address of it's
96 // function descriptor, which is what these two values end up being
97 // in assembly.
98 Constant *InitVals[] = {&IFunc, IFunc.getResolver()};
99 GV->setInitializer(ConstantStruct::get(IFuncPairType, InitVals));
100
101 // Liveness of __update_foo is dependent on liveness of ifunc foo.
102 IFunc.setMetadata(LLVMContext::MD_implicit_ref,
104
105 // An implicit.ref creates linkage dependency, so make function foo require
106 // the constructor that calls each ifunc's resolver and saves the result in
107 // the ifunc's function descriptor.
108 IFunc.addMetadata(
109 LLVMContext::MD_implicit_ref,
110 *MDNode::get(Ctx, ValueAsMetadata::get(IFuncConstructorDecl)));
111 }
112
113 return true;
114}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
Machine Check Debug Module
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file contains some templates that are useful if you are working with the STL at all.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:114
Target-Independent Code Generator Pass Configuration Options pass.
This pass exposes codegen information to IR-level passes.
static LLVM_ABI Constant * get(StructType *T, ArrayRef< Constant * > V)
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition GlobalValue.h:61
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1572
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
static LLVM_ABI StructType * get(LLVMContext &Context, ArrayRef< Type * > Elements, bool isPacked=false)
This static method is the primary way to create a literal StructType.
Definition Type.cpp:413
static LLVM_ABI ValueAsMetadata * get(Value *V)
Definition Metadata.cpp:509
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
ModulePass * createPPCPrepareIFuncsOnAIXPass()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:207
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559