xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Utils/ModuleUtils.cpp (revision d686ce931cab72612a9e1ada9fe99d65e11a32a3)
10b57cec5SDimitry Andric //===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This family of functions perform manipulations on Modules.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
14480093f4SDimitry Andric #include "llvm/Analysis/VectorUtils.h"
1506c3fb27SDimitry Andric #include "llvm/ADT/SmallString.h"
160b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
170b57cec5SDimitry Andric #include "llvm/IR/Function.h"
180b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h"
19bdd1243dSDimitry Andric #include "llvm/IR/MDBuilder.h"
200b57cec5SDimitry Andric #include "llvm/IR/Module.h"
210fca6ea1SDimitry Andric #include "llvm/Support/MD5.h"
220b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
23bdd1243dSDimitry Andric #include "llvm/Support/xxhash.h"
2406c3fb27SDimitry Andric 
250b57cec5SDimitry Andric using namespace llvm;
260b57cec5SDimitry Andric 
275ffd83dbSDimitry Andric #define DEBUG_TYPE "moduleutils"
285ffd83dbSDimitry Andric 
29bdd1243dSDimitry Andric static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F,
300b57cec5SDimitry Andric                                 int Priority, Constant *Data) {
310b57cec5SDimitry Andric   IRBuilder<> IRB(M.getContext());
320b57cec5SDimitry Andric   FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false);
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric   // Get the current set of static global constructors and add the new ctor
350b57cec5SDimitry Andric   // to the list.
360b57cec5SDimitry Andric   SmallVector<Constant *, 16> CurrentCtors;
3706c3fb27SDimitry Andric   StructType *EltTy;
38bdd1243dSDimitry Andric   if (GlobalVariable *GVCtor = M.getNamedGlobal(ArrayName)) {
3906c3fb27SDimitry Andric     EltTy = cast<StructType>(GVCtor->getValueType()->getArrayElementType());
400b57cec5SDimitry Andric     if (Constant *Init = GVCtor->getInitializer()) {
410b57cec5SDimitry Andric       unsigned n = Init->getNumOperands();
420b57cec5SDimitry Andric       CurrentCtors.reserve(n + 1);
430b57cec5SDimitry Andric       for (unsigned i = 0; i != n; ++i)
440b57cec5SDimitry Andric         CurrentCtors.push_back(cast<Constant>(Init->getOperand(i)));
450b57cec5SDimitry Andric     }
460b57cec5SDimitry Andric     GVCtor->eraseFromParent();
4706c3fb27SDimitry Andric   } else {
485f757f3fSDimitry Andric     EltTy = StructType::get(IRB.getInt32Ty(),
495f757f3fSDimitry Andric                             PointerType::get(FnTy, F->getAddressSpace()),
505f757f3fSDimitry Andric                             IRB.getPtrTy());
510b57cec5SDimitry Andric   }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   // Build a 3 field global_ctor entry.  We don't take a comdat key.
540b57cec5SDimitry Andric   Constant *CSVals[3];
550b57cec5SDimitry Andric   CSVals[0] = IRB.getInt32(Priority);
560b57cec5SDimitry Andric   CSVals[1] = F;
575f757f3fSDimitry Andric   CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getPtrTy())
585f757f3fSDimitry Andric                    : Constant::getNullValue(IRB.getPtrTy());
590b57cec5SDimitry Andric   Constant *RuntimeCtorInit =
60bdd1243dSDimitry Andric       ConstantStruct::get(EltTy, ArrayRef(CSVals, EltTy->getNumElements()));
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   CurrentCtors.push_back(RuntimeCtorInit);
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   // Create a new initializer.
650b57cec5SDimitry Andric   ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size());
660b57cec5SDimitry Andric   Constant *NewInit = ConstantArray::get(AT, CurrentCtors);
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   // Create the new global variable and replace all uses of
690b57cec5SDimitry Andric   // the old global variable with the new one.
700b57cec5SDimitry Andric   (void)new GlobalVariable(M, NewInit->getType(), false,
71bdd1243dSDimitry Andric                            GlobalValue::AppendingLinkage, NewInit, ArrayName);
720b57cec5SDimitry Andric }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data) {
750b57cec5SDimitry Andric   appendToGlobalArray("llvm.global_ctors", M, F, Priority, Data);
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data) {
790b57cec5SDimitry Andric   appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data);
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
82bdd1243dSDimitry Andric static void collectUsedGlobals(GlobalVariable *GV,
83bdd1243dSDimitry Andric                                SmallSetVector<Constant *, 16> &Init) {
84bdd1243dSDimitry Andric   if (!GV || !GV->hasInitializer())
85bdd1243dSDimitry Andric     return;
86bdd1243dSDimitry Andric 
878bcb0991SDimitry Andric   auto *CA = cast<ConstantArray>(GV->getInitializer());
88bdd1243dSDimitry Andric   for (Use &Op : CA->operands())
89bdd1243dSDimitry Andric     Init.insert(cast<Constant>(Op));
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
92bdd1243dSDimitry Andric static void appendToUsedList(Module &M, StringRef Name, ArrayRef<GlobalValue *> Values) {
93bdd1243dSDimitry Andric   GlobalVariable *GV = M.getGlobalVariable(Name);
94bdd1243dSDimitry Andric 
95bdd1243dSDimitry Andric   SmallSetVector<Constant *, 16> Init;
96bdd1243dSDimitry Andric   collectUsedGlobals(GV, Init);
97bdd1243dSDimitry Andric   if (GV)
98bdd1243dSDimitry Andric     GV->eraseFromParent();
99bdd1243dSDimitry Andric 
1005f757f3fSDimitry Andric   Type *ArrayEltTy = llvm::PointerType::getUnqual(M.getContext());
101bdd1243dSDimitry Andric   for (auto *V : Values)
102bdd1243dSDimitry Andric     Init.insert(ConstantExpr::getPointerBitCastOrAddrSpaceCast(V, ArrayEltTy));
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   if (Init.empty())
1050b57cec5SDimitry Andric     return;
1060b57cec5SDimitry Andric 
107bdd1243dSDimitry Andric   ArrayType *ATy = ArrayType::get(ArrayEltTy, Init.size());
1080b57cec5SDimitry Andric   GV = new llvm::GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage,
109bdd1243dSDimitry Andric                                 ConstantArray::get(ATy, Init.getArrayRef()),
110bdd1243dSDimitry Andric                                 Name);
1110b57cec5SDimitry Andric   GV->setSection("llvm.metadata");
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric void llvm::appendToUsed(Module &M, ArrayRef<GlobalValue *> Values) {
1150b57cec5SDimitry Andric   appendToUsedList(M, "llvm.used", Values);
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric void llvm::appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values) {
1190b57cec5SDimitry Andric   appendToUsedList(M, "llvm.compiler.used", Values);
1200b57cec5SDimitry Andric }
1210b57cec5SDimitry Andric 
122bdd1243dSDimitry Andric static void removeFromUsedList(Module &M, StringRef Name,
123bdd1243dSDimitry Andric                                function_ref<bool(Constant *)> ShouldRemove) {
124bdd1243dSDimitry Andric   GlobalVariable *GV = M.getNamedGlobal(Name);
125bdd1243dSDimitry Andric   if (!GV)
126bdd1243dSDimitry Andric     return;
127bdd1243dSDimitry Andric 
128bdd1243dSDimitry Andric   SmallSetVector<Constant *, 16> Init;
129bdd1243dSDimitry Andric   collectUsedGlobals(GV, Init);
130bdd1243dSDimitry Andric 
131bdd1243dSDimitry Andric   Type *ArrayEltTy = cast<ArrayType>(GV->getValueType())->getElementType();
132bdd1243dSDimitry Andric 
133bdd1243dSDimitry Andric   SmallVector<Constant *, 16> NewInit;
134bdd1243dSDimitry Andric   for (Constant *MaybeRemoved : Init) {
135bdd1243dSDimitry Andric     if (!ShouldRemove(MaybeRemoved->stripPointerCasts()))
136bdd1243dSDimitry Andric       NewInit.push_back(MaybeRemoved);
137bdd1243dSDimitry Andric   }
138bdd1243dSDimitry Andric 
139bdd1243dSDimitry Andric   if (!NewInit.empty()) {
140bdd1243dSDimitry Andric     ArrayType *ATy = ArrayType::get(ArrayEltTy, NewInit.size());
141bdd1243dSDimitry Andric     GlobalVariable *NewGV =
142bdd1243dSDimitry Andric         new GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage,
143bdd1243dSDimitry Andric                            ConstantArray::get(ATy, NewInit), "", GV,
144bdd1243dSDimitry Andric                            GV->getThreadLocalMode(), GV->getAddressSpace());
145bdd1243dSDimitry Andric     NewGV->setSection(GV->getSection());
146bdd1243dSDimitry Andric     NewGV->takeName(GV);
147bdd1243dSDimitry Andric   }
148bdd1243dSDimitry Andric 
149bdd1243dSDimitry Andric   GV->eraseFromParent();
150bdd1243dSDimitry Andric }
151bdd1243dSDimitry Andric 
152bdd1243dSDimitry Andric void llvm::removeFromUsedLists(Module &M,
153bdd1243dSDimitry Andric                                function_ref<bool(Constant *)> ShouldRemove) {
154bdd1243dSDimitry Andric   removeFromUsedList(M, "llvm.used", ShouldRemove);
155bdd1243dSDimitry Andric   removeFromUsedList(M, "llvm.compiler.used", ShouldRemove);
156bdd1243dSDimitry Andric }
157bdd1243dSDimitry Andric 
158bdd1243dSDimitry Andric void llvm::setKCFIType(Module &M, Function &F, StringRef MangledType) {
159bdd1243dSDimitry Andric   if (!M.getModuleFlag("kcfi"))
160bdd1243dSDimitry Andric     return;
161bdd1243dSDimitry Andric   // Matches CodeGenModule::CreateKCFITypeId in Clang.
162bdd1243dSDimitry Andric   LLVMContext &Ctx = M.getContext();
163bdd1243dSDimitry Andric   MDBuilder MDB(Ctx);
164*d686ce93SDimitry Andric   std::string Type = MangledType.str();
165*d686ce93SDimitry Andric   if (M.getModuleFlag("cfi-normalize-integers"))
166*d686ce93SDimitry Andric     Type += ".normalized";
167*d686ce93SDimitry Andric   F.setMetadata(LLVMContext::MD_kcfi_type,
168bdd1243dSDimitry Andric                 MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
169bdd1243dSDimitry Andric                                      Type::getInt32Ty(Ctx),
170*d686ce93SDimitry Andric                                      static_cast<uint32_t>(xxHash64(Type))))));
171bdd1243dSDimitry Andric   // If the module was compiled with -fpatchable-function-entry, ensure
172bdd1243dSDimitry Andric   // we use the same patchable-function-prefix.
173bdd1243dSDimitry Andric   if (auto *MD = mdconst::extract_or_null<ConstantInt>(
174bdd1243dSDimitry Andric           M.getModuleFlag("kcfi-offset"))) {
175bdd1243dSDimitry Andric     if (unsigned Offset = MD->getZExtValue())
176bdd1243dSDimitry Andric       F.addFnAttr("patchable-function-prefix", std::to_string(Offset));
177bdd1243dSDimitry Andric   }
178bdd1243dSDimitry Andric }
179bdd1243dSDimitry Andric 
180bdd1243dSDimitry Andric FunctionCallee llvm::declareSanitizerInitFunction(Module &M, StringRef InitName,
181bdd1243dSDimitry Andric                                                   ArrayRef<Type *> InitArgTypes,
182bdd1243dSDimitry Andric                                                   bool Weak) {
1830b57cec5SDimitry Andric   assert(!InitName.empty() && "Expected init function name");
184bdd1243dSDimitry Andric   auto *VoidTy = Type::getVoidTy(M.getContext());
185bdd1243dSDimitry Andric   auto *FnTy = FunctionType::get(VoidTy, InitArgTypes, false);
186bdd1243dSDimitry Andric   auto FnCallee = M.getOrInsertFunction(InitName, FnTy);
187bdd1243dSDimitry Andric   auto *Fn = cast<Function>(FnCallee.getCallee());
188bdd1243dSDimitry Andric   if (Weak && Fn->isDeclaration())
189bdd1243dSDimitry Andric     Fn->setLinkage(Function::ExternalWeakLinkage);
190bdd1243dSDimitry Andric   return FnCallee;
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric 
1935ffd83dbSDimitry Andric Function *llvm::createSanitizerCtor(Module &M, StringRef CtorName) {
194fe6060f1SDimitry Andric   Function *Ctor = Function::createWithDefaultAttr(
1955ffd83dbSDimitry Andric       FunctionType::get(Type::getVoidTy(M.getContext()), false),
196bdd1243dSDimitry Andric       GlobalValue::InternalLinkage, M.getDataLayout().getProgramAddressSpace(),
197bdd1243dSDimitry Andric       CtorName, &M);
198349cc55cSDimitry Andric   Ctor->addFnAttr(Attribute::NoUnwind);
199bdd1243dSDimitry Andric   setKCFIType(M, *Ctor, "_ZTSFvvE"); // void (*)(void)
2005ffd83dbSDimitry Andric   BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor);
2015ffd83dbSDimitry Andric   ReturnInst::Create(M.getContext(), CtorBB);
202fe6060f1SDimitry Andric   // Ensure Ctor cannot be discarded, even if in a comdat.
203fe6060f1SDimitry Andric   appendToUsed(M, {Ctor});
2045ffd83dbSDimitry Andric   return Ctor;
2055ffd83dbSDimitry Andric }
2065ffd83dbSDimitry Andric 
2070b57cec5SDimitry Andric std::pair<Function *, FunctionCallee> llvm::createSanitizerCtorAndInitFunctions(
2080b57cec5SDimitry Andric     Module &M, StringRef CtorName, StringRef InitName,
2090b57cec5SDimitry Andric     ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
210bdd1243dSDimitry Andric     StringRef VersionCheckName, bool Weak) {
2110b57cec5SDimitry Andric   assert(!InitName.empty() && "Expected init function name");
2120b57cec5SDimitry Andric   assert(InitArgs.size() == InitArgTypes.size() &&
2130b57cec5SDimitry Andric          "Sanitizer's init function expects different number of arguments");
2140b57cec5SDimitry Andric   FunctionCallee InitFunction =
215bdd1243dSDimitry Andric       declareSanitizerInitFunction(M, InitName, InitArgTypes, Weak);
2165ffd83dbSDimitry Andric   Function *Ctor = createSanitizerCtor(M, CtorName);
217bdd1243dSDimitry Andric   IRBuilder<> IRB(M.getContext());
218bdd1243dSDimitry Andric 
219bdd1243dSDimitry Andric   BasicBlock *RetBB = &Ctor->getEntryBlock();
220bdd1243dSDimitry Andric   if (Weak) {
221bdd1243dSDimitry Andric     RetBB->setName("ret");
222bdd1243dSDimitry Andric     auto *EntryBB = BasicBlock::Create(M.getContext(), "entry", Ctor, RetBB);
223bdd1243dSDimitry Andric     auto *CallInitBB =
224bdd1243dSDimitry Andric         BasicBlock::Create(M.getContext(), "callfunc", Ctor, RetBB);
225bdd1243dSDimitry Andric     auto *InitFn = cast<Function>(InitFunction.getCallee());
226bdd1243dSDimitry Andric     auto *InitFnPtr =
227bdd1243dSDimitry Andric         PointerType::get(InitFn->getType(), InitFn->getAddressSpace());
228bdd1243dSDimitry Andric     IRB.SetInsertPoint(EntryBB);
229bdd1243dSDimitry Andric     Value *InitNotNull =
230bdd1243dSDimitry Andric         IRB.CreateICmpNE(InitFn, ConstantPointerNull::get(InitFnPtr));
231bdd1243dSDimitry Andric     IRB.CreateCondBr(InitNotNull, CallInitBB, RetBB);
232bdd1243dSDimitry Andric     IRB.SetInsertPoint(CallInitBB);
233bdd1243dSDimitry Andric   } else {
234bdd1243dSDimitry Andric     IRB.SetInsertPoint(RetBB->getTerminator());
235bdd1243dSDimitry Andric   }
236bdd1243dSDimitry Andric 
2370b57cec5SDimitry Andric   IRB.CreateCall(InitFunction, InitArgs);
2380b57cec5SDimitry Andric   if (!VersionCheckName.empty()) {
2390b57cec5SDimitry Andric     FunctionCallee VersionCheckFunction = M.getOrInsertFunction(
2400b57cec5SDimitry Andric         VersionCheckName, FunctionType::get(IRB.getVoidTy(), {}, false),
2410b57cec5SDimitry Andric         AttributeList());
2420b57cec5SDimitry Andric     IRB.CreateCall(VersionCheckFunction, {});
2430b57cec5SDimitry Andric   }
244bdd1243dSDimitry Andric 
245bdd1243dSDimitry Andric   if (Weak)
246bdd1243dSDimitry Andric     IRB.CreateBr(RetBB);
247bdd1243dSDimitry Andric 
2480b57cec5SDimitry Andric   return std::make_pair(Ctor, InitFunction);
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric std::pair<Function *, FunctionCallee>
2520b57cec5SDimitry Andric llvm::getOrCreateSanitizerCtorAndInitFunctions(
2530b57cec5SDimitry Andric     Module &M, StringRef CtorName, StringRef InitName,
2540b57cec5SDimitry Andric     ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
2550b57cec5SDimitry Andric     function_ref<void(Function *, FunctionCallee)> FunctionsCreatedCallback,
256bdd1243dSDimitry Andric     StringRef VersionCheckName, bool Weak) {
2570b57cec5SDimitry Andric   assert(!CtorName.empty() && "Expected ctor function name");
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   if (Function *Ctor = M.getFunction(CtorName))
2600b57cec5SDimitry Andric     // FIXME: Sink this logic into the module, similar to the handling of
2610b57cec5SDimitry Andric     // globals. This will make moving to a concurrent model much easier.
262349cc55cSDimitry Andric     if (Ctor->arg_empty() ||
2630b57cec5SDimitry Andric         Ctor->getReturnType() == Type::getVoidTy(M.getContext()))
264bdd1243dSDimitry Andric       return {Ctor,
265bdd1243dSDimitry Andric               declareSanitizerInitFunction(M, InitName, InitArgTypes, Weak)};
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   Function *Ctor;
2680b57cec5SDimitry Andric   FunctionCallee InitFunction;
2690b57cec5SDimitry Andric   std::tie(Ctor, InitFunction) = llvm::createSanitizerCtorAndInitFunctions(
270bdd1243dSDimitry Andric       M, CtorName, InitName, InitArgTypes, InitArgs, VersionCheckName, Weak);
2710b57cec5SDimitry Andric   FunctionsCreatedCallback(Ctor, InitFunction);
2720b57cec5SDimitry Andric   return std::make_pair(Ctor, InitFunction);
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric void llvm::filterDeadComdatFunctions(
27604eeddc0SDimitry Andric     SmallVectorImpl<Function *> &DeadComdatFunctions) {
27704eeddc0SDimitry Andric   SmallPtrSet<Function *, 32> MaybeDeadFunctions;
27804eeddc0SDimitry Andric   SmallPtrSet<Comdat *, 32> MaybeDeadComdats;
2790b57cec5SDimitry Andric   for (Function *F : DeadComdatFunctions) {
28004eeddc0SDimitry Andric     MaybeDeadFunctions.insert(F);
28104eeddc0SDimitry Andric     if (Comdat *C = F->getComdat())
28204eeddc0SDimitry Andric       MaybeDeadComdats.insert(C);
28304eeddc0SDimitry Andric   }
28404eeddc0SDimitry Andric 
28504eeddc0SDimitry Andric   // Find comdats for which all users are dead now.
28604eeddc0SDimitry Andric   SmallPtrSet<Comdat *, 32> DeadComdats;
28704eeddc0SDimitry Andric   for (Comdat *C : MaybeDeadComdats) {
28804eeddc0SDimitry Andric     auto IsUserDead = [&](GlobalObject *GO) {
28904eeddc0SDimitry Andric       auto *F = dyn_cast<Function>(GO);
29004eeddc0SDimitry Andric       return F && MaybeDeadFunctions.contains(F);
29104eeddc0SDimitry Andric     };
29204eeddc0SDimitry Andric     if (all_of(C->getUsers(), IsUserDead))
29304eeddc0SDimitry Andric       DeadComdats.insert(C);
29404eeddc0SDimitry Andric   }
29504eeddc0SDimitry Andric 
29604eeddc0SDimitry Andric   // Only keep functions which have no comdat or a dead comdat.
29704eeddc0SDimitry Andric   erase_if(DeadComdatFunctions, [&](Function *F) {
2980b57cec5SDimitry Andric     Comdat *C = F->getComdat();
29904eeddc0SDimitry Andric     return C && !DeadComdats.contains(C);
3000b57cec5SDimitry Andric   });
3010b57cec5SDimitry Andric }
3020b57cec5SDimitry Andric 
3030b57cec5SDimitry Andric std::string llvm::getUniqueModuleId(Module *M) {
3040b57cec5SDimitry Andric   MD5 Md5;
3050b57cec5SDimitry Andric   bool ExportsSymbols = false;
3060b57cec5SDimitry Andric   auto AddGlobal = [&](GlobalValue &GV) {
3075f757f3fSDimitry Andric     if (GV.isDeclaration() || GV.getName().starts_with("llvm.") ||
3080b57cec5SDimitry Andric         !GV.hasExternalLinkage() || GV.hasComdat())
3090b57cec5SDimitry Andric       return;
3100b57cec5SDimitry Andric     ExportsSymbols = true;
3110b57cec5SDimitry Andric     Md5.update(GV.getName());
3120b57cec5SDimitry Andric     Md5.update(ArrayRef<uint8_t>{0});
3130b57cec5SDimitry Andric   };
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   for (auto &F : *M)
3160b57cec5SDimitry Andric     AddGlobal(F);
3170b57cec5SDimitry Andric   for (auto &GV : M->globals())
3180b57cec5SDimitry Andric     AddGlobal(GV);
3190b57cec5SDimitry Andric   for (auto &GA : M->aliases())
3200b57cec5SDimitry Andric     AddGlobal(GA);
3210b57cec5SDimitry Andric   for (auto &IF : M->ifuncs())
3220b57cec5SDimitry Andric     AddGlobal(IF);
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   if (!ExportsSymbols)
3250b57cec5SDimitry Andric     return "";
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   MD5::MD5Result R;
3280b57cec5SDimitry Andric   Md5.final(R);
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   SmallString<32> Str;
3310b57cec5SDimitry Andric   MD5::stringifyResult(R, Str);
332fe6060f1SDimitry Andric   return ("." + Str).str();
3330b57cec5SDimitry Andric }
334480093f4SDimitry Andric 
3351fd87a68SDimitry Andric void llvm::embedBufferInModule(Module &M, MemoryBufferRef Buf,
33681ad6265SDimitry Andric                                StringRef SectionName, Align Alignment) {
33781ad6265SDimitry Andric   // Embed the memory buffer into the module.
3381fd87a68SDimitry Andric   Constant *ModuleConstant = ConstantDataArray::get(
339bdd1243dSDimitry Andric       M.getContext(), ArrayRef(Buf.getBufferStart(), Buf.getBufferSize()));
3401fd87a68SDimitry Andric   GlobalVariable *GV = new GlobalVariable(
3411fd87a68SDimitry Andric       M, ModuleConstant->getType(), true, GlobalValue::PrivateLinkage,
3421fd87a68SDimitry Andric       ModuleConstant, "llvm.embedded.object");
3431fd87a68SDimitry Andric   GV->setSection(SectionName);
34481ad6265SDimitry Andric   GV->setAlignment(Alignment);
3451fd87a68SDimitry Andric 
346753f127fSDimitry Andric   LLVMContext &Ctx = M.getContext();
347753f127fSDimitry Andric   NamedMDNode *MD = M.getOrInsertNamedMetadata("llvm.embedded.objects");
348753f127fSDimitry Andric   Metadata *MDVals[] = {ConstantAsMetadata::get(GV),
349753f127fSDimitry Andric                         MDString::get(Ctx, SectionName)};
350753f127fSDimitry Andric 
351753f127fSDimitry Andric   MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
352753f127fSDimitry Andric   GV->setMetadata(LLVMContext::MD_exclude, llvm::MDNode::get(Ctx, {}));
353753f127fSDimitry Andric 
3541fd87a68SDimitry Andric   appendToCompilerUsed(M, GV);
3551fd87a68SDimitry Andric }
356bdd1243dSDimitry Andric 
357bdd1243dSDimitry Andric bool llvm::lowerGlobalIFuncUsersAsGlobalCtor(
358bdd1243dSDimitry Andric     Module &M, ArrayRef<GlobalIFunc *> FilteredIFuncsToLower) {
359bdd1243dSDimitry Andric   SmallVector<GlobalIFunc *, 32> AllIFuncs;
360bdd1243dSDimitry Andric   ArrayRef<GlobalIFunc *> IFuncsToLower = FilteredIFuncsToLower;
361bdd1243dSDimitry Andric   if (FilteredIFuncsToLower.empty()) { // Default to lowering all ifuncs
362bdd1243dSDimitry Andric     for (GlobalIFunc &GI : M.ifuncs())
363bdd1243dSDimitry Andric       AllIFuncs.push_back(&GI);
364bdd1243dSDimitry Andric     IFuncsToLower = AllIFuncs;
365bdd1243dSDimitry Andric   }
366bdd1243dSDimitry Andric 
367bdd1243dSDimitry Andric   bool UnhandledUsers = false;
368bdd1243dSDimitry Andric   LLVMContext &Ctx = M.getContext();
369bdd1243dSDimitry Andric   const DataLayout &DL = M.getDataLayout();
370bdd1243dSDimitry Andric 
371bdd1243dSDimitry Andric   PointerType *TableEntryTy =
37206c3fb27SDimitry Andric       PointerType::get(Ctx, DL.getProgramAddressSpace());
373bdd1243dSDimitry Andric 
374bdd1243dSDimitry Andric   ArrayType *FuncPtrTableTy =
375bdd1243dSDimitry Andric       ArrayType::get(TableEntryTy, IFuncsToLower.size());
376bdd1243dSDimitry Andric 
377bdd1243dSDimitry Andric   Align PtrAlign = DL.getABITypeAlign(TableEntryTy);
378bdd1243dSDimitry Andric 
379bdd1243dSDimitry Andric   // Create a global table of function pointers we'll initialize in a global
380bdd1243dSDimitry Andric   // constructor.
381bdd1243dSDimitry Andric   auto *FuncPtrTable = new GlobalVariable(
382bdd1243dSDimitry Andric       M, FuncPtrTableTy, false, GlobalValue::InternalLinkage,
383bdd1243dSDimitry Andric       PoisonValue::get(FuncPtrTableTy), "", nullptr,
384bdd1243dSDimitry Andric       GlobalVariable::NotThreadLocal, DL.getDefaultGlobalsAddressSpace());
385bdd1243dSDimitry Andric   FuncPtrTable->setAlignment(PtrAlign);
386bdd1243dSDimitry Andric 
387bdd1243dSDimitry Andric   // Create a function to initialize the function pointer table.
388bdd1243dSDimitry Andric   Function *NewCtor = Function::Create(
389bdd1243dSDimitry Andric       FunctionType::get(Type::getVoidTy(Ctx), false), Function::InternalLinkage,
390bdd1243dSDimitry Andric       DL.getProgramAddressSpace(), "", &M);
391bdd1243dSDimitry Andric 
392bdd1243dSDimitry Andric   BasicBlock *BB = BasicBlock::Create(Ctx, "", NewCtor);
393bdd1243dSDimitry Andric   IRBuilder<> InitBuilder(BB);
394bdd1243dSDimitry Andric 
395bdd1243dSDimitry Andric   size_t TableIndex = 0;
396bdd1243dSDimitry Andric   for (GlobalIFunc *GI : IFuncsToLower) {
397bdd1243dSDimitry Andric     Function *ResolvedFunction = GI->getResolverFunction();
398bdd1243dSDimitry Andric 
399bdd1243dSDimitry Andric     // We don't know what to pass to a resolver function taking arguments
400bdd1243dSDimitry Andric     //
401bdd1243dSDimitry Andric     // FIXME: Is this even valid? clang and gcc don't complain but this
402bdd1243dSDimitry Andric     // probably should be invalid IR. We could just pass through undef.
403bdd1243dSDimitry Andric     if (!std::empty(ResolvedFunction->getFunctionType()->params())) {
404bdd1243dSDimitry Andric       LLVM_DEBUG(dbgs() << "Not lowering ifunc resolver function "
405bdd1243dSDimitry Andric                         << ResolvedFunction->getName() << " with parameters\n");
406bdd1243dSDimitry Andric       UnhandledUsers = true;
407bdd1243dSDimitry Andric       continue;
408bdd1243dSDimitry Andric     }
409bdd1243dSDimitry Andric 
410bdd1243dSDimitry Andric     // Initialize the function pointer table.
411bdd1243dSDimitry Andric     CallInst *ResolvedFunc = InitBuilder.CreateCall(ResolvedFunction);
412bdd1243dSDimitry Andric     Value *Casted = InitBuilder.CreatePointerCast(ResolvedFunc, TableEntryTy);
413bdd1243dSDimitry Andric     Constant *GEP = cast<Constant>(InitBuilder.CreateConstInBoundsGEP2_32(
414bdd1243dSDimitry Andric         FuncPtrTableTy, FuncPtrTable, 0, TableIndex++));
415bdd1243dSDimitry Andric     InitBuilder.CreateAlignedStore(Casted, GEP, PtrAlign);
416bdd1243dSDimitry Andric 
417bdd1243dSDimitry Andric     // Update all users to load a pointer from the global table.
418bdd1243dSDimitry Andric     for (User *User : make_early_inc_range(GI->users())) {
419bdd1243dSDimitry Andric       Instruction *UserInst = dyn_cast<Instruction>(User);
420bdd1243dSDimitry Andric       if (!UserInst) {
421bdd1243dSDimitry Andric         // TODO: Should handle constantexpr casts in user instructions. Probably
422bdd1243dSDimitry Andric         // can't do much about constant initializers.
423bdd1243dSDimitry Andric         UnhandledUsers = true;
424bdd1243dSDimitry Andric         continue;
425bdd1243dSDimitry Andric       }
426bdd1243dSDimitry Andric 
427bdd1243dSDimitry Andric       IRBuilder<> UseBuilder(UserInst);
428bdd1243dSDimitry Andric       LoadInst *ResolvedTarget =
429bdd1243dSDimitry Andric           UseBuilder.CreateAlignedLoad(TableEntryTy, GEP, PtrAlign);
430bdd1243dSDimitry Andric       Value *ResolvedCast =
431bdd1243dSDimitry Andric           UseBuilder.CreatePointerCast(ResolvedTarget, GI->getType());
432bdd1243dSDimitry Andric       UserInst->replaceUsesOfWith(GI, ResolvedCast);
433bdd1243dSDimitry Andric     }
434bdd1243dSDimitry Andric 
435bdd1243dSDimitry Andric     // If we handled all users, erase the ifunc.
436bdd1243dSDimitry Andric     if (GI->use_empty())
437bdd1243dSDimitry Andric       GI->eraseFromParent();
438bdd1243dSDimitry Andric   }
439bdd1243dSDimitry Andric 
440bdd1243dSDimitry Andric   InitBuilder.CreateRetVoid();
441bdd1243dSDimitry Andric 
44206c3fb27SDimitry Andric   PointerType *ConstantDataTy = PointerType::get(Ctx, 0);
443bdd1243dSDimitry Andric 
444bdd1243dSDimitry Andric   // TODO: Is this the right priority? Probably should be before any other
445bdd1243dSDimitry Andric   // constructors?
446bdd1243dSDimitry Andric   const int Priority = 10;
447bdd1243dSDimitry Andric   appendToGlobalCtors(M, NewCtor, Priority,
448bdd1243dSDimitry Andric                       ConstantPointerNull::get(ConstantDataTy));
449bdd1243dSDimitry Andric   return UnhandledUsers;
450bdd1243dSDimitry Andric }
451