LLVM 24.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 "llvm/ADT/Statistic.h"
18#include "llvm/IR/Module.h"
19#include <cassert>
20
21using namespace llvm;
22
23#define DEBUG_TYPE "ppc-prep-ifunc-aix"
24
25STATISTIC(NumIFuncs, "Number of IFuncs prepared");
26
27namespace {
28class PPCPrepareIFuncsOnAIX : public ModulePass {
29public:
30 static char ID;
31
32 PPCPrepareIFuncsOnAIX() : ModulePass(ID) {}
33
34 bool runOnModule(Module &M) override;
35
36 StringRef getPassName() const override {
37 return "PPC Prepare for AIX IFunc lowering";
38 }
39};
40} // namespace
41
42char PPCPrepareIFuncsOnAIX::ID = 0;
43
44INITIALIZE_PASS(PPCPrepareIFuncsOnAIX, DEBUG_TYPE,
45 "PPC Prepare for AIX IFunc lowering", false, false)
46
48 return new PPCPrepareIFuncsOnAIX();
49}
50
51// For each ifunc `foo` with a resolver `foo_resolver`, create a global variable
52// `__update_foo` in the `ifunc_sec` section, representing the pair:
53// { ptr @foo, ptr @foo_resolver }
54// The compiler arranges for the constructor function `__init_ifuncs` to be
55// included on the link step. The constructor walks the `ifunc_sec` section,
56// calling the resolver function and storing the result in foo's descriptor.
57// On AIX, the address of a function is the address of its descriptor, so the
58// constructor accesses foo's descriptor from the first field of the pair.
59//
60// Since the global `__update_foo` is unreferenced, it's liveness needs to be
61// associated to the liveness of ifunc `foo`
62//
63bool PPCPrepareIFuncsOnAIX::runOnModule(Module &M) {
64 if (M.ifuncs().empty())
65 return false;
66
67 const DataLayout &DL = M.getDataLayout();
68 LLVMContext &Ctx = M.getContext();
69 auto *PtrTy = PointerType::getUnqual(Ctx);
70 StringRef IFuncUpdatePrefix = "__update_";
71 StringRef IFuncUpdateSectionName = "__ifunc_sec";
72 StructType *IFuncPairType = StructType::get(PtrTy, PtrTy);
73
74 StringRef IFuncConstructorName = "__init_ifuncs";
75 auto *IFuncConstructorFnType =
76 FunctionType::get(Type::getVoidTy(Ctx), {}, /*isVarArg=*/false);
77 auto *IFuncConstructorDecl = cast<Function>(
78 M.getOrInsertFunction(IFuncConstructorName, IFuncConstructorFnType)
79 .getCallee());
80
81 for (GlobalIFunc &IFunc : M.ifuncs()) {
82 NumIFuncs++;
83 LLVM_DEBUG(dbgs() << "expanding ifunc " << IFunc.getName() << "\n");
84 // @__update_foo = private global { ptr @foo, ptr @foo_resolver },
85 // section "ifunc_sec"
86 std::string Name = (Twine(IFuncUpdatePrefix) + IFunc.getName()).str();
87 auto *GV = new GlobalVariable(M, IFuncPairType, /*isConstant*/ false,
88 GlobalValue::PrivateLinkage, nullptr, Name);
89 GV->setAlignment(DL.getPointerPrefAlignment());
90 GV->setSection(IFuncUpdateSectionName);
91
92 // Note that on AIX, the address of a function is the address of it's
93 // function descriptor, which is what these two values end up being
94 // in assembly.
95 Constant *InitVals[] = {&IFunc, IFunc.getResolver()};
96 GV->setInitializer(ConstantStruct::get(IFuncPairType, InitVals));
97
98 // Liveness of __update_foo is dependent on liveness of ifunc foo.
99 IFunc.setMetadata(LLVMContext::MD_implicit_ref,
101
102 // An implicit.ref creates linkage dependency, so make function foo require
103 // the constructor that calls each ifunc's resolver and saves the result in
104 // the ifunc's function descriptor.
105 IFunc.addMetadata(
106 LLVMContext::MD_implicit_ref,
107 *MDNode::get(Ctx, ValueAsMetadata::get(IFuncConstructorDecl)));
108 }
109
110 return true;
111}
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
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:119
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:1567
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:68
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:477
static LLVM_ABI ValueAsMetadata * get(Value *V)
Definition Metadata.cpp:510
This is an optimization pass for GlobalISel generic memory operations.
ModulePass * createPPCPrepareIFuncsOnAIXPass()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559