xref: /src/contrib/llvm-project/llvm/lib/Transforms/Utils/ModuleUtils.cpp (revision d686ce931cab72612a9e1ada9fe99d65e11a32a3)
163faed5bSDimitry Andric //===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===//
263faed5bSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
663faed5bSDimitry Andric //
763faed5bSDimitry Andric //===----------------------------------------------------------------------===//
863faed5bSDimitry Andric //
963faed5bSDimitry Andric // This family of functions perform manipulations on Modules.
1063faed5bSDimitry Andric //
1163faed5bSDimitry Andric //===----------------------------------------------------------------------===//
1263faed5bSDimitry Andric 
1363faed5bSDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
14706b4fc4SDimitry Andric #include "llvm/Analysis/VectorUtils.h"
157fa27ce4SDimitry Andric #include "llvm/ADT/SmallString.h"
164a16efa3SDimitry Andric #include "llvm/IR/DerivedTypes.h"
174a16efa3SDimitry Andric #include "llvm/IR/Function.h"
184a16efa3SDimitry Andric #include "llvm/IR/IRBuilder.h"
19e3b55780SDimitry Andric #include "llvm/IR/MDBuilder.h"
204a16efa3SDimitry Andric #include "llvm/IR/Module.h"
21ac9a064cSDimitry Andric #include "llvm/Support/MD5.h"
225a5ac124SDimitry Andric #include "llvm/Support/raw_ostream.h"
23e3b55780SDimitry Andric #include "llvm/Support/xxhash.h"
247fa27ce4SDimitry Andric 
2563faed5bSDimitry Andric using namespace llvm;
2663faed5bSDimitry Andric 
27cfca06d7SDimitry Andric #define DEBUG_TYPE "moduleutils"
28cfca06d7SDimitry Andric 
appendToGlobalArray(StringRef ArrayName,Module & M,Function * F,int Priority,Constant * Data)29e3b55780SDimitry Andric static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F,
3001095a5dSDimitry Andric                                 int Priority, Constant *Data) {
3163faed5bSDimitry Andric   IRBuilder<> IRB(M.getContext());
3263faed5bSDimitry Andric   FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false);
3363faed5bSDimitry Andric 
3463faed5bSDimitry Andric   // Get the current set of static global constructors and add the new ctor
3563faed5bSDimitry Andric   // to the list.
3663faed5bSDimitry Andric   SmallVector<Constant *, 16> CurrentCtors;
377fa27ce4SDimitry Andric   StructType *EltTy;
38e3b55780SDimitry Andric   if (GlobalVariable *GVCtor = M.getNamedGlobal(ArrayName)) {
397fa27ce4SDimitry Andric     EltTy = cast<StructType>(GVCtor->getValueType()->getArrayElementType());
4063faed5bSDimitry Andric     if (Constant *Init = GVCtor->getInitializer()) {
4163faed5bSDimitry Andric       unsigned n = Init->getNumOperands();
4263faed5bSDimitry Andric       CurrentCtors.reserve(n + 1);
43e6d15924SDimitry Andric       for (unsigned i = 0; i != n; ++i)
44e6d15924SDimitry Andric         CurrentCtors.push_back(cast<Constant>(Init->getOperand(i)));
4563faed5bSDimitry Andric     }
4663faed5bSDimitry Andric     GVCtor->eraseFromParent();
477fa27ce4SDimitry Andric   } else {
48b1c73532SDimitry Andric     EltTy = StructType::get(IRB.getInt32Ty(),
49b1c73532SDimitry Andric                             PointerType::get(FnTy, F->getAddressSpace()),
50b1c73532SDimitry Andric                             IRB.getPtrTy());
5163faed5bSDimitry Andric   }
5263faed5bSDimitry Andric 
53e6d15924SDimitry Andric   // Build a 3 field global_ctor entry.  We don't take a comdat key.
545ca98fd9SDimitry Andric   Constant *CSVals[3];
555ca98fd9SDimitry Andric   CSVals[0] = IRB.getInt32(Priority);
565ca98fd9SDimitry Andric   CSVals[1] = F;
57b1c73532SDimitry Andric   CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getPtrTy())
58b1c73532SDimitry Andric                    : Constant::getNullValue(IRB.getPtrTy());
595ca98fd9SDimitry Andric   Constant *RuntimeCtorInit =
60e3b55780SDimitry Andric       ConstantStruct::get(EltTy, ArrayRef(CSVals, EltTy->getNumElements()));
615ca98fd9SDimitry Andric 
6263faed5bSDimitry Andric   CurrentCtors.push_back(RuntimeCtorInit);
6363faed5bSDimitry Andric 
6463faed5bSDimitry Andric   // Create a new initializer.
655ca98fd9SDimitry Andric   ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size());
6663faed5bSDimitry Andric   Constant *NewInit = ConstantArray::get(AT, CurrentCtors);
6763faed5bSDimitry Andric 
6863faed5bSDimitry Andric   // Create the new global variable and replace all uses of
6963faed5bSDimitry Andric   // the old global variable with the new one.
7063faed5bSDimitry Andric   (void)new GlobalVariable(M, NewInit->getType(), false,
71e3b55780SDimitry Andric                            GlobalValue::AppendingLinkage, NewInit, ArrayName);
7263faed5bSDimitry Andric }
7363faed5bSDimitry Andric 
appendToGlobalCtors(Module & M,Function * F,int Priority,Constant * Data)7401095a5dSDimitry Andric void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data) {
7501095a5dSDimitry Andric   appendToGlobalArray("llvm.global_ctors", M, F, Priority, Data);
7663faed5bSDimitry Andric }
7763faed5bSDimitry Andric 
appendToGlobalDtors(Module & M,Function * F,int Priority,Constant * Data)7801095a5dSDimitry Andric void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data) {
7901095a5dSDimitry Andric   appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data);
80f8af5cf6SDimitry Andric }
815a5ac124SDimitry Andric 
collectUsedGlobals(GlobalVariable * GV,SmallSetVector<Constant *,16> & Init)82e3b55780SDimitry Andric static void collectUsedGlobals(GlobalVariable *GV,
83e3b55780SDimitry Andric                                SmallSetVector<Constant *, 16> &Init) {
84e3b55780SDimitry Andric   if (!GV || !GV->hasInitializer())
85e3b55780SDimitry Andric     return;
86e3b55780SDimitry Andric 
871d5ae102SDimitry Andric   auto *CA = cast<ConstantArray>(GV->getInitializer());
88e3b55780SDimitry Andric   for (Use &Op : CA->operands())
89e3b55780SDimitry Andric     Init.insert(cast<Constant>(Op));
90b915e9e0SDimitry Andric }
91b915e9e0SDimitry Andric 
appendToUsedList(Module & M,StringRef Name,ArrayRef<GlobalValue * > Values)92e3b55780SDimitry Andric static void appendToUsedList(Module &M, StringRef Name, ArrayRef<GlobalValue *> Values) {
93e3b55780SDimitry Andric   GlobalVariable *GV = M.getGlobalVariable(Name);
94e3b55780SDimitry Andric 
95e3b55780SDimitry Andric   SmallSetVector<Constant *, 16> Init;
96e3b55780SDimitry Andric   collectUsedGlobals(GV, Init);
97e3b55780SDimitry Andric   if (GV)
98e3b55780SDimitry Andric     GV->eraseFromParent();
99e3b55780SDimitry Andric 
100b1c73532SDimitry Andric   Type *ArrayEltTy = llvm::PointerType::getUnqual(M.getContext());
101e3b55780SDimitry Andric   for (auto *V : Values)
102e3b55780SDimitry Andric     Init.insert(ConstantExpr::getPointerBitCastOrAddrSpaceCast(V, ArrayEltTy));
103b915e9e0SDimitry Andric 
104b915e9e0SDimitry Andric   if (Init.empty())
105b915e9e0SDimitry Andric     return;
106b915e9e0SDimitry Andric 
107e3b55780SDimitry Andric   ArrayType *ATy = ArrayType::get(ArrayEltTy, Init.size());
108b915e9e0SDimitry Andric   GV = new llvm::GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage,
109e3b55780SDimitry Andric                                 ConstantArray::get(ATy, Init.getArrayRef()),
110e3b55780SDimitry Andric                                 Name);
111b915e9e0SDimitry Andric   GV->setSection("llvm.metadata");
112b915e9e0SDimitry Andric }
113b915e9e0SDimitry Andric 
appendToUsed(Module & M,ArrayRef<GlobalValue * > Values)114b915e9e0SDimitry Andric void llvm::appendToUsed(Module &M, ArrayRef<GlobalValue *> Values) {
115b915e9e0SDimitry Andric   appendToUsedList(M, "llvm.used", Values);
116b915e9e0SDimitry Andric }
117b915e9e0SDimitry Andric 
appendToCompilerUsed(Module & M,ArrayRef<GlobalValue * > Values)118b915e9e0SDimitry Andric void llvm::appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values) {
119b915e9e0SDimitry Andric   appendToUsedList(M, "llvm.compiler.used", Values);
120b915e9e0SDimitry Andric }
121b915e9e0SDimitry Andric 
removeFromUsedList(Module & M,StringRef Name,function_ref<bool (Constant *)> ShouldRemove)122e3b55780SDimitry Andric static void removeFromUsedList(Module &M, StringRef Name,
123e3b55780SDimitry Andric                                function_ref<bool(Constant *)> ShouldRemove) {
124e3b55780SDimitry Andric   GlobalVariable *GV = M.getNamedGlobal(Name);
125e3b55780SDimitry Andric   if (!GV)
126e3b55780SDimitry Andric     return;
127e3b55780SDimitry Andric 
128e3b55780SDimitry Andric   SmallSetVector<Constant *, 16> Init;
129e3b55780SDimitry Andric   collectUsedGlobals(GV, Init);
130e3b55780SDimitry Andric 
131e3b55780SDimitry Andric   Type *ArrayEltTy = cast<ArrayType>(GV->getValueType())->getElementType();
132e3b55780SDimitry Andric 
133e3b55780SDimitry Andric   SmallVector<Constant *, 16> NewInit;
134e3b55780SDimitry Andric   for (Constant *MaybeRemoved : Init) {
135e3b55780SDimitry Andric     if (!ShouldRemove(MaybeRemoved->stripPointerCasts()))
136e3b55780SDimitry Andric       NewInit.push_back(MaybeRemoved);
137e3b55780SDimitry Andric   }
138e3b55780SDimitry Andric 
139e3b55780SDimitry Andric   if (!NewInit.empty()) {
140e3b55780SDimitry Andric     ArrayType *ATy = ArrayType::get(ArrayEltTy, NewInit.size());
141e3b55780SDimitry Andric     GlobalVariable *NewGV =
142e3b55780SDimitry Andric         new GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage,
143e3b55780SDimitry Andric                            ConstantArray::get(ATy, NewInit), "", GV,
144e3b55780SDimitry Andric                            GV->getThreadLocalMode(), GV->getAddressSpace());
145e3b55780SDimitry Andric     NewGV->setSection(GV->getSection());
146e3b55780SDimitry Andric     NewGV->takeName(GV);
147e3b55780SDimitry Andric   }
148e3b55780SDimitry Andric 
149e3b55780SDimitry Andric   GV->eraseFromParent();
150e3b55780SDimitry Andric }
151e3b55780SDimitry Andric 
removeFromUsedLists(Module & M,function_ref<bool (Constant *)> ShouldRemove)152e3b55780SDimitry Andric void llvm::removeFromUsedLists(Module &M,
153e3b55780SDimitry Andric                                function_ref<bool(Constant *)> ShouldRemove) {
154e3b55780SDimitry Andric   removeFromUsedList(M, "llvm.used", ShouldRemove);
155e3b55780SDimitry Andric   removeFromUsedList(M, "llvm.compiler.used", ShouldRemove);
156e3b55780SDimitry Andric }
157e3b55780SDimitry Andric 
setKCFIType(Module & M,Function & F,StringRef MangledType)158e3b55780SDimitry Andric void llvm::setKCFIType(Module &M, Function &F, StringRef MangledType) {
159e3b55780SDimitry Andric   if (!M.getModuleFlag("kcfi"))
160e3b55780SDimitry Andric     return;
161e3b55780SDimitry Andric   // Matches CodeGenModule::CreateKCFITypeId in Clang.
162e3b55780SDimitry Andric   LLVMContext &Ctx = M.getContext();
163e3b55780SDimitry Andric   MDBuilder MDB(Ctx);
164efdccd83SDimitry Andric   std::string Type = MangledType.str();
165efdccd83SDimitry Andric   if (M.getModuleFlag("cfi-normalize-integers"))
166efdccd83SDimitry Andric     Type += ".normalized";
167efdccd83SDimitry Andric   F.setMetadata(LLVMContext::MD_kcfi_type,
168e3b55780SDimitry Andric                 MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
169e3b55780SDimitry Andric                                      Type::getInt32Ty(Ctx),
170efdccd83SDimitry Andric                                      static_cast<uint32_t>(xxHash64(Type))))));
171e3b55780SDimitry Andric   // If the module was compiled with -fpatchable-function-entry, ensure
172e3b55780SDimitry Andric   // we use the same patchable-function-prefix.
173e3b55780SDimitry Andric   if (auto *MD = mdconst::extract_or_null<ConstantInt>(
174e3b55780SDimitry Andric           M.getModuleFlag("kcfi-offset"))) {
175e3b55780SDimitry Andric     if (unsigned Offset = MD->getZExtValue())
176e3b55780SDimitry Andric       F.addFnAttr("patchable-function-prefix", std::to_string(Offset));
177e3b55780SDimitry Andric   }
178e3b55780SDimitry Andric }
179e3b55780SDimitry Andric 
declareSanitizerInitFunction(Module & M,StringRef InitName,ArrayRef<Type * > InitArgTypes,bool Weak)180e3b55780SDimitry Andric FunctionCallee llvm::declareSanitizerInitFunction(Module &M, StringRef InitName,
181e3b55780SDimitry Andric                                                   ArrayRef<Type *> InitArgTypes,
182e3b55780SDimitry Andric                                                   bool Weak) {
18371d5a254SDimitry Andric   assert(!InitName.empty() && "Expected init function name");
184e3b55780SDimitry Andric   auto *VoidTy = Type::getVoidTy(M.getContext());
185e3b55780SDimitry Andric   auto *FnTy = FunctionType::get(VoidTy, InitArgTypes, false);
186e3b55780SDimitry Andric   auto FnCallee = M.getOrInsertFunction(InitName, FnTy);
187e3b55780SDimitry Andric   auto *Fn = cast<Function>(FnCallee.getCallee());
188e3b55780SDimitry Andric   if (Weak && Fn->isDeclaration())
189e3b55780SDimitry Andric     Fn->setLinkage(Function::ExternalWeakLinkage);
190e3b55780SDimitry Andric   return FnCallee;
19171d5a254SDimitry Andric }
19271d5a254SDimitry Andric 
createSanitizerCtor(Module & M,StringRef CtorName)193cfca06d7SDimitry Andric Function *llvm::createSanitizerCtor(Module &M, StringRef CtorName) {
194344a3780SDimitry Andric   Function *Ctor = Function::createWithDefaultAttr(
195cfca06d7SDimitry Andric       FunctionType::get(Type::getVoidTy(M.getContext()), false),
196e3b55780SDimitry Andric       GlobalValue::InternalLinkage, M.getDataLayout().getProgramAddressSpace(),
197e3b55780SDimitry Andric       CtorName, &M);
198c0981da4SDimitry Andric   Ctor->addFnAttr(Attribute::NoUnwind);
199e3b55780SDimitry Andric   setKCFIType(M, *Ctor, "_ZTSFvvE"); // void (*)(void)
200cfca06d7SDimitry Andric   BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor);
201cfca06d7SDimitry Andric   ReturnInst::Create(M.getContext(), CtorBB);
202344a3780SDimitry Andric   // Ensure Ctor cannot be discarded, even if in a comdat.
203344a3780SDimitry Andric   appendToUsed(M, {Ctor});
204cfca06d7SDimitry Andric   return Ctor;
205cfca06d7SDimitry Andric }
206cfca06d7SDimitry Andric 
createSanitizerCtorAndInitFunctions(Module & M,StringRef CtorName,StringRef InitName,ArrayRef<Type * > InitArgTypes,ArrayRef<Value * > InitArgs,StringRef VersionCheckName,bool Weak)207e6d15924SDimitry Andric std::pair<Function *, FunctionCallee> llvm::createSanitizerCtorAndInitFunctions(
2085a5ac124SDimitry Andric     Module &M, StringRef CtorName, StringRef InitName,
209dd58ef01SDimitry Andric     ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
210e3b55780SDimitry Andric     StringRef VersionCheckName, bool Weak) {
2115a5ac124SDimitry Andric   assert(!InitName.empty() && "Expected init function name");
212b915e9e0SDimitry Andric   assert(InitArgs.size() == InitArgTypes.size() &&
2135a5ac124SDimitry Andric          "Sanitizer's init function expects different number of arguments");
214e6d15924SDimitry Andric   FunctionCallee InitFunction =
215e3b55780SDimitry Andric       declareSanitizerInitFunction(M, InitName, InitArgTypes, Weak);
216cfca06d7SDimitry Andric   Function *Ctor = createSanitizerCtor(M, CtorName);
217e3b55780SDimitry Andric   IRBuilder<> IRB(M.getContext());
218e3b55780SDimitry Andric 
219e3b55780SDimitry Andric   BasicBlock *RetBB = &Ctor->getEntryBlock();
220e3b55780SDimitry Andric   if (Weak) {
221e3b55780SDimitry Andric     RetBB->setName("ret");
222e3b55780SDimitry Andric     auto *EntryBB = BasicBlock::Create(M.getContext(), "entry", Ctor, RetBB);
223e3b55780SDimitry Andric     auto *CallInitBB =
224e3b55780SDimitry Andric         BasicBlock::Create(M.getContext(), "callfunc", Ctor, RetBB);
225e3b55780SDimitry Andric     auto *InitFn = cast<Function>(InitFunction.getCallee());
226e3b55780SDimitry Andric     auto *InitFnPtr =
227e3b55780SDimitry Andric         PointerType::get(InitFn->getType(), InitFn->getAddressSpace());
228e3b55780SDimitry Andric     IRB.SetInsertPoint(EntryBB);
229e3b55780SDimitry Andric     Value *InitNotNull =
230e3b55780SDimitry Andric         IRB.CreateICmpNE(InitFn, ConstantPointerNull::get(InitFnPtr));
231e3b55780SDimitry Andric     IRB.CreateCondBr(InitNotNull, CallInitBB, RetBB);
232e3b55780SDimitry Andric     IRB.SetInsertPoint(CallInitBB);
233e3b55780SDimitry Andric   } else {
234e3b55780SDimitry Andric     IRB.SetInsertPoint(RetBB->getTerminator());
235e3b55780SDimitry Andric   }
236e3b55780SDimitry Andric 
2375a5ac124SDimitry Andric   IRB.CreateCall(InitFunction, InitArgs);
238dd58ef01SDimitry Andric   if (!VersionCheckName.empty()) {
239e6d15924SDimitry Andric     FunctionCallee VersionCheckFunction = M.getOrInsertFunction(
240dd58ef01SDimitry Andric         VersionCheckName, FunctionType::get(IRB.getVoidTy(), {}, false),
241e6d15924SDimitry Andric         AttributeList());
242dd58ef01SDimitry Andric     IRB.CreateCall(VersionCheckFunction, {});
243dd58ef01SDimitry Andric   }
244e3b55780SDimitry Andric 
245e3b55780SDimitry Andric   if (Weak)
246e3b55780SDimitry Andric     IRB.CreateBr(RetBB);
247e3b55780SDimitry Andric 
2485a5ac124SDimitry Andric   return std::make_pair(Ctor, InitFunction);
2495a5ac124SDimitry Andric }
250b915e9e0SDimitry Andric 
251e6d15924SDimitry Andric std::pair<Function *, FunctionCallee>
getOrCreateSanitizerCtorAndInitFunctions(Module & M,StringRef CtorName,StringRef InitName,ArrayRef<Type * > InitArgTypes,ArrayRef<Value * > InitArgs,function_ref<void (Function *,FunctionCallee)> FunctionsCreatedCallback,StringRef VersionCheckName,bool Weak)252d8e91e46SDimitry Andric llvm::getOrCreateSanitizerCtorAndInitFunctions(
253d8e91e46SDimitry Andric     Module &M, StringRef CtorName, StringRef InitName,
254d8e91e46SDimitry Andric     ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
255e6d15924SDimitry Andric     function_ref<void(Function *, FunctionCallee)> FunctionsCreatedCallback,
256e3b55780SDimitry Andric     StringRef VersionCheckName, bool Weak) {
257d8e91e46SDimitry Andric   assert(!CtorName.empty() && "Expected ctor function name");
258d8e91e46SDimitry Andric 
259d8e91e46SDimitry Andric   if (Function *Ctor = M.getFunction(CtorName))
260d8e91e46SDimitry Andric     // FIXME: Sink this logic into the module, similar to the handling of
261d8e91e46SDimitry Andric     // globals. This will make moving to a concurrent model much easier.
262c0981da4SDimitry Andric     if (Ctor->arg_empty() ||
263d8e91e46SDimitry Andric         Ctor->getReturnType() == Type::getVoidTy(M.getContext()))
264e3b55780SDimitry Andric       return {Ctor,
265e3b55780SDimitry Andric               declareSanitizerInitFunction(M, InitName, InitArgTypes, Weak)};
266d8e91e46SDimitry Andric 
267e6d15924SDimitry Andric   Function *Ctor;
268e6d15924SDimitry Andric   FunctionCallee InitFunction;
269d8e91e46SDimitry Andric   std::tie(Ctor, InitFunction) = llvm::createSanitizerCtorAndInitFunctions(
270e3b55780SDimitry Andric       M, CtorName, InitName, InitArgTypes, InitArgs, VersionCheckName, Weak);
271d8e91e46SDimitry Andric   FunctionsCreatedCallback(Ctor, InitFunction);
272d8e91e46SDimitry Andric   return std::make_pair(Ctor, InitFunction);
273d8e91e46SDimitry Andric }
274d8e91e46SDimitry Andric 
filterDeadComdatFunctions(SmallVectorImpl<Function * > & DeadComdatFunctions)275b915e9e0SDimitry Andric void llvm::filterDeadComdatFunctions(
2766f8fc217SDimitry Andric     SmallVectorImpl<Function *> &DeadComdatFunctions) {
2776f8fc217SDimitry Andric   SmallPtrSet<Function *, 32> MaybeDeadFunctions;
2786f8fc217SDimitry Andric   SmallPtrSet<Comdat *, 32> MaybeDeadComdats;
279b915e9e0SDimitry Andric   for (Function *F : DeadComdatFunctions) {
2806f8fc217SDimitry Andric     MaybeDeadFunctions.insert(F);
2816f8fc217SDimitry Andric     if (Comdat *C = F->getComdat())
2826f8fc217SDimitry Andric       MaybeDeadComdats.insert(C);
2836f8fc217SDimitry Andric   }
2846f8fc217SDimitry Andric 
2856f8fc217SDimitry Andric   // Find comdats for which all users are dead now.
2866f8fc217SDimitry Andric   SmallPtrSet<Comdat *, 32> DeadComdats;
2876f8fc217SDimitry Andric   for (Comdat *C : MaybeDeadComdats) {
2886f8fc217SDimitry Andric     auto IsUserDead = [&](GlobalObject *GO) {
2896f8fc217SDimitry Andric       auto *F = dyn_cast<Function>(GO);
2906f8fc217SDimitry Andric       return F && MaybeDeadFunctions.contains(F);
2916f8fc217SDimitry Andric     };
2926f8fc217SDimitry Andric     if (all_of(C->getUsers(), IsUserDead))
2936f8fc217SDimitry Andric       DeadComdats.insert(C);
2946f8fc217SDimitry Andric   }
2956f8fc217SDimitry Andric 
2966f8fc217SDimitry Andric   // Only keep functions which have no comdat or a dead comdat.
2976f8fc217SDimitry Andric   erase_if(DeadComdatFunctions, [&](Function *F) {
298b915e9e0SDimitry Andric     Comdat *C = F->getComdat();
2996f8fc217SDimitry Andric     return C && !DeadComdats.contains(C);
300b915e9e0SDimitry Andric   });
301b915e9e0SDimitry Andric }
302a303c417SDimitry Andric 
getUniqueModuleId(Module * M)303a303c417SDimitry Andric std::string llvm::getUniqueModuleId(Module *M) {
304a303c417SDimitry Andric   MD5 Md5;
305a303c417SDimitry Andric   bool ExportsSymbols = false;
306a303c417SDimitry Andric   auto AddGlobal = [&](GlobalValue &GV) {
307b1c73532SDimitry Andric     if (GV.isDeclaration() || GV.getName().starts_with("llvm.") ||
308044eb2f6SDimitry Andric         !GV.hasExternalLinkage() || GV.hasComdat())
309a303c417SDimitry Andric       return;
310a303c417SDimitry Andric     ExportsSymbols = true;
311a303c417SDimitry Andric     Md5.update(GV.getName());
312a303c417SDimitry Andric     Md5.update(ArrayRef<uint8_t>{0});
313a303c417SDimitry Andric   };
314a303c417SDimitry Andric 
315a303c417SDimitry Andric   for (auto &F : *M)
316a303c417SDimitry Andric     AddGlobal(F);
317a303c417SDimitry Andric   for (auto &GV : M->globals())
318a303c417SDimitry Andric     AddGlobal(GV);
319a303c417SDimitry Andric   for (auto &GA : M->aliases())
320a303c417SDimitry Andric     AddGlobal(GA);
321a303c417SDimitry Andric   for (auto &IF : M->ifuncs())
322a303c417SDimitry Andric     AddGlobal(IF);
323a303c417SDimitry Andric 
324a303c417SDimitry Andric   if (!ExportsSymbols)
325a303c417SDimitry Andric     return "";
326a303c417SDimitry Andric 
327a303c417SDimitry Andric   MD5::MD5Result R;
328a303c417SDimitry Andric   Md5.final(R);
329a303c417SDimitry Andric 
330a303c417SDimitry Andric   SmallString<32> Str;
331a303c417SDimitry Andric   MD5::stringifyResult(R, Str);
332344a3780SDimitry Andric   return ("." + Str).str();
333a303c417SDimitry Andric }
334706b4fc4SDimitry Andric 
embedBufferInModule(Module & M,MemoryBufferRef Buf,StringRef SectionName,Align Alignment)335ecbca9f5SDimitry Andric void llvm::embedBufferInModule(Module &M, MemoryBufferRef Buf,
336145449b1SDimitry Andric                                StringRef SectionName, Align Alignment) {
337145449b1SDimitry Andric   // Embed the memory buffer into the module.
338ecbca9f5SDimitry Andric   Constant *ModuleConstant = ConstantDataArray::get(
339e3b55780SDimitry Andric       M.getContext(), ArrayRef(Buf.getBufferStart(), Buf.getBufferSize()));
340ecbca9f5SDimitry Andric   GlobalVariable *GV = new GlobalVariable(
341ecbca9f5SDimitry Andric       M, ModuleConstant->getType(), true, GlobalValue::PrivateLinkage,
342ecbca9f5SDimitry Andric       ModuleConstant, "llvm.embedded.object");
343ecbca9f5SDimitry Andric   GV->setSection(SectionName);
344145449b1SDimitry Andric   GV->setAlignment(Alignment);
345ecbca9f5SDimitry Andric 
3461f917f69SDimitry Andric   LLVMContext &Ctx = M.getContext();
3471f917f69SDimitry Andric   NamedMDNode *MD = M.getOrInsertNamedMetadata("llvm.embedded.objects");
3481f917f69SDimitry Andric   Metadata *MDVals[] = {ConstantAsMetadata::get(GV),
3491f917f69SDimitry Andric                         MDString::get(Ctx, SectionName)};
3501f917f69SDimitry Andric 
3511f917f69SDimitry Andric   MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
3521f917f69SDimitry Andric   GV->setMetadata(LLVMContext::MD_exclude, llvm::MDNode::get(Ctx, {}));
3531f917f69SDimitry Andric 
354ecbca9f5SDimitry Andric   appendToCompilerUsed(M, GV);
355ecbca9f5SDimitry Andric }
356e3b55780SDimitry Andric 
lowerGlobalIFuncUsersAsGlobalCtor(Module & M,ArrayRef<GlobalIFunc * > FilteredIFuncsToLower)357e3b55780SDimitry Andric bool llvm::lowerGlobalIFuncUsersAsGlobalCtor(
358e3b55780SDimitry Andric     Module &M, ArrayRef<GlobalIFunc *> FilteredIFuncsToLower) {
359e3b55780SDimitry Andric   SmallVector<GlobalIFunc *, 32> AllIFuncs;
360e3b55780SDimitry Andric   ArrayRef<GlobalIFunc *> IFuncsToLower = FilteredIFuncsToLower;
361e3b55780SDimitry Andric   if (FilteredIFuncsToLower.empty()) { // Default to lowering all ifuncs
362e3b55780SDimitry Andric     for (GlobalIFunc &GI : M.ifuncs())
363e3b55780SDimitry Andric       AllIFuncs.push_back(&GI);
364e3b55780SDimitry Andric     IFuncsToLower = AllIFuncs;
365e3b55780SDimitry Andric   }
366e3b55780SDimitry Andric 
367e3b55780SDimitry Andric   bool UnhandledUsers = false;
368e3b55780SDimitry Andric   LLVMContext &Ctx = M.getContext();
369e3b55780SDimitry Andric   const DataLayout &DL = M.getDataLayout();
370e3b55780SDimitry Andric 
371e3b55780SDimitry Andric   PointerType *TableEntryTy =
3727fa27ce4SDimitry Andric       PointerType::get(Ctx, DL.getProgramAddressSpace());
373e3b55780SDimitry Andric 
374e3b55780SDimitry Andric   ArrayType *FuncPtrTableTy =
375e3b55780SDimitry Andric       ArrayType::get(TableEntryTy, IFuncsToLower.size());
376e3b55780SDimitry Andric 
377e3b55780SDimitry Andric   Align PtrAlign = DL.getABITypeAlign(TableEntryTy);
378e3b55780SDimitry Andric 
379e3b55780SDimitry Andric   // Create a global table of function pointers we'll initialize in a global
380e3b55780SDimitry Andric   // constructor.
381e3b55780SDimitry Andric   auto *FuncPtrTable = new GlobalVariable(
382e3b55780SDimitry Andric       M, FuncPtrTableTy, false, GlobalValue::InternalLinkage,
383e3b55780SDimitry Andric       PoisonValue::get(FuncPtrTableTy), "", nullptr,
384e3b55780SDimitry Andric       GlobalVariable::NotThreadLocal, DL.getDefaultGlobalsAddressSpace());
385e3b55780SDimitry Andric   FuncPtrTable->setAlignment(PtrAlign);
386e3b55780SDimitry Andric 
387e3b55780SDimitry Andric   // Create a function to initialize the function pointer table.
388e3b55780SDimitry Andric   Function *NewCtor = Function::Create(
389e3b55780SDimitry Andric       FunctionType::get(Type::getVoidTy(Ctx), false), Function::InternalLinkage,
390e3b55780SDimitry Andric       DL.getProgramAddressSpace(), "", &M);
391e3b55780SDimitry Andric 
392e3b55780SDimitry Andric   BasicBlock *BB = BasicBlock::Create(Ctx, "", NewCtor);
393e3b55780SDimitry Andric   IRBuilder<> InitBuilder(BB);
394e3b55780SDimitry Andric 
395e3b55780SDimitry Andric   size_t TableIndex = 0;
396e3b55780SDimitry Andric   for (GlobalIFunc *GI : IFuncsToLower) {
397e3b55780SDimitry Andric     Function *ResolvedFunction = GI->getResolverFunction();
398e3b55780SDimitry Andric 
399e3b55780SDimitry Andric     // We don't know what to pass to a resolver function taking arguments
400e3b55780SDimitry Andric     //
401e3b55780SDimitry Andric     // FIXME: Is this even valid? clang and gcc don't complain but this
402e3b55780SDimitry Andric     // probably should be invalid IR. We could just pass through undef.
403e3b55780SDimitry Andric     if (!std::empty(ResolvedFunction->getFunctionType()->params())) {
404e3b55780SDimitry Andric       LLVM_DEBUG(dbgs() << "Not lowering ifunc resolver function "
405e3b55780SDimitry Andric                         << ResolvedFunction->getName() << " with parameters\n");
406e3b55780SDimitry Andric       UnhandledUsers = true;
407e3b55780SDimitry Andric       continue;
408e3b55780SDimitry Andric     }
409e3b55780SDimitry Andric 
410e3b55780SDimitry Andric     // Initialize the function pointer table.
411e3b55780SDimitry Andric     CallInst *ResolvedFunc = InitBuilder.CreateCall(ResolvedFunction);
412e3b55780SDimitry Andric     Value *Casted = InitBuilder.CreatePointerCast(ResolvedFunc, TableEntryTy);
413e3b55780SDimitry Andric     Constant *GEP = cast<Constant>(InitBuilder.CreateConstInBoundsGEP2_32(
414e3b55780SDimitry Andric         FuncPtrTableTy, FuncPtrTable, 0, TableIndex++));
415e3b55780SDimitry Andric     InitBuilder.CreateAlignedStore(Casted, GEP, PtrAlign);
416e3b55780SDimitry Andric 
417e3b55780SDimitry Andric     // Update all users to load a pointer from the global table.
418e3b55780SDimitry Andric     for (User *User : make_early_inc_range(GI->users())) {
419e3b55780SDimitry Andric       Instruction *UserInst = dyn_cast<Instruction>(User);
420e3b55780SDimitry Andric       if (!UserInst) {
421e3b55780SDimitry Andric         // TODO: Should handle constantexpr casts in user instructions. Probably
422e3b55780SDimitry Andric         // can't do much about constant initializers.
423e3b55780SDimitry Andric         UnhandledUsers = true;
424e3b55780SDimitry Andric         continue;
425e3b55780SDimitry Andric       }
426e3b55780SDimitry Andric 
427e3b55780SDimitry Andric       IRBuilder<> UseBuilder(UserInst);
428e3b55780SDimitry Andric       LoadInst *ResolvedTarget =
429e3b55780SDimitry Andric           UseBuilder.CreateAlignedLoad(TableEntryTy, GEP, PtrAlign);
430e3b55780SDimitry Andric       Value *ResolvedCast =
431e3b55780SDimitry Andric           UseBuilder.CreatePointerCast(ResolvedTarget, GI->getType());
432e3b55780SDimitry Andric       UserInst->replaceUsesOfWith(GI, ResolvedCast);
433e3b55780SDimitry Andric     }
434e3b55780SDimitry Andric 
435e3b55780SDimitry Andric     // If we handled all users, erase the ifunc.
436e3b55780SDimitry Andric     if (GI->use_empty())
437e3b55780SDimitry Andric       GI->eraseFromParent();
438e3b55780SDimitry Andric   }
439e3b55780SDimitry Andric 
440e3b55780SDimitry Andric   InitBuilder.CreateRetVoid();
441e3b55780SDimitry Andric 
4427fa27ce4SDimitry Andric   PointerType *ConstantDataTy = PointerType::get(Ctx, 0);
443e3b55780SDimitry Andric 
444e3b55780SDimitry Andric   // TODO: Is this the right priority? Probably should be before any other
445e3b55780SDimitry Andric   // constructors?
446e3b55780SDimitry Andric   const int Priority = 10;
447e3b55780SDimitry Andric   appendToGlobalCtors(M, NewCtor, Priority,
448e3b55780SDimitry Andric                       ConstantPointerNull::get(ConstantDataTy));
449e3b55780SDimitry Andric   return UnhandledUsers;
450e3b55780SDimitry Andric }
451