xref: /openbsd-src/gnu/llvm/llvm/lib/Transforms/Utils/ModuleUtils.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This family of functions perform manipulations on Modules.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #include "llvm/Transforms/Utils/ModuleUtils.h"
1409467b48Spatrick #include "llvm/Analysis/VectorUtils.h"
1509467b48Spatrick #include "llvm/IR/DerivedTypes.h"
1609467b48Spatrick #include "llvm/IR/Function.h"
1709467b48Spatrick #include "llvm/IR/IRBuilder.h"
18*d415bd75Srobert #include "llvm/IR/MDBuilder.h"
1909467b48Spatrick #include "llvm/IR/Module.h"
2009467b48Spatrick #include "llvm/Support/raw_ostream.h"
21*d415bd75Srobert #include "llvm/Support/xxhash.h"
2209467b48Spatrick using namespace llvm;
2309467b48Spatrick 
24097a140dSpatrick #define DEBUG_TYPE "moduleutils"
25097a140dSpatrick 
appendToGlobalArray(StringRef ArrayName,Module & M,Function * F,int Priority,Constant * Data)26*d415bd75Srobert static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F,
2709467b48Spatrick                                 int Priority, Constant *Data) {
2809467b48Spatrick   IRBuilder<> IRB(M.getContext());
2909467b48Spatrick   FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false);
3009467b48Spatrick 
3109467b48Spatrick   // Get the current set of static global constructors and add the new ctor
3209467b48Spatrick   // to the list.
3309467b48Spatrick   SmallVector<Constant *, 16> CurrentCtors;
3409467b48Spatrick   StructType *EltTy = StructType::get(
35*d415bd75Srobert       IRB.getInt32Ty(), PointerType::get(FnTy, F->getAddressSpace()),
36*d415bd75Srobert       IRB.getInt8PtrTy());
37*d415bd75Srobert 
38*d415bd75Srobert   if (GlobalVariable *GVCtor = M.getNamedGlobal(ArrayName)) {
3909467b48Spatrick     if (Constant *Init = GVCtor->getInitializer()) {
4009467b48Spatrick       unsigned n = Init->getNumOperands();
4109467b48Spatrick       CurrentCtors.reserve(n + 1);
4209467b48Spatrick       for (unsigned i = 0; i != n; ++i)
4309467b48Spatrick         CurrentCtors.push_back(cast<Constant>(Init->getOperand(i)));
4409467b48Spatrick     }
4509467b48Spatrick     GVCtor->eraseFromParent();
4609467b48Spatrick   }
4709467b48Spatrick 
4809467b48Spatrick   // Build a 3 field global_ctor entry.  We don't take a comdat key.
4909467b48Spatrick   Constant *CSVals[3];
5009467b48Spatrick   CSVals[0] = IRB.getInt32(Priority);
5109467b48Spatrick   CSVals[1] = F;
5209467b48Spatrick   CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getInt8PtrTy())
5309467b48Spatrick                    : Constant::getNullValue(IRB.getInt8PtrTy());
5409467b48Spatrick   Constant *RuntimeCtorInit =
55*d415bd75Srobert       ConstantStruct::get(EltTy, ArrayRef(CSVals, EltTy->getNumElements()));
5609467b48Spatrick 
5709467b48Spatrick   CurrentCtors.push_back(RuntimeCtorInit);
5809467b48Spatrick 
5909467b48Spatrick   // Create a new initializer.
6009467b48Spatrick   ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size());
6109467b48Spatrick   Constant *NewInit = ConstantArray::get(AT, CurrentCtors);
6209467b48Spatrick 
6309467b48Spatrick   // Create the new global variable and replace all uses of
6409467b48Spatrick   // the old global variable with the new one.
6509467b48Spatrick   (void)new GlobalVariable(M, NewInit->getType(), false,
66*d415bd75Srobert                            GlobalValue::AppendingLinkage, NewInit, ArrayName);
6709467b48Spatrick }
6809467b48Spatrick 
appendToGlobalCtors(Module & M,Function * F,int Priority,Constant * Data)6909467b48Spatrick void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data) {
7009467b48Spatrick   appendToGlobalArray("llvm.global_ctors", M, F, Priority, Data);
7109467b48Spatrick }
7209467b48Spatrick 
appendToGlobalDtors(Module & M,Function * F,int Priority,Constant * Data)7309467b48Spatrick void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data) {
7409467b48Spatrick   appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data);
7509467b48Spatrick }
7609467b48Spatrick 
collectUsedGlobals(GlobalVariable * GV,SmallSetVector<Constant *,16> & Init)77*d415bd75Srobert static void collectUsedGlobals(GlobalVariable *GV,
78*d415bd75Srobert                                SmallSetVector<Constant *, 16> &Init) {
79*d415bd75Srobert   if (!GV || !GV->hasInitializer())
80*d415bd75Srobert     return;
81*d415bd75Srobert 
8209467b48Spatrick   auto *CA = cast<ConstantArray>(GV->getInitializer());
83*d415bd75Srobert   for (Use &Op : CA->operands())
84*d415bd75Srobert     Init.insert(cast<Constant>(Op));
8509467b48Spatrick }
8609467b48Spatrick 
appendToUsedList(Module & M,StringRef Name,ArrayRef<GlobalValue * > Values)87*d415bd75Srobert static void appendToUsedList(Module &M, StringRef Name, ArrayRef<GlobalValue *> Values) {
88*d415bd75Srobert   GlobalVariable *GV = M.getGlobalVariable(Name);
89*d415bd75Srobert 
90*d415bd75Srobert   SmallSetVector<Constant *, 16> Init;
91*d415bd75Srobert   collectUsedGlobals(GV, Init);
92*d415bd75Srobert   if (GV)
93*d415bd75Srobert     GV->eraseFromParent();
94*d415bd75Srobert 
95*d415bd75Srobert   Type *ArrayEltTy = llvm::Type::getInt8PtrTy(M.getContext());
96*d415bd75Srobert   for (auto *V : Values)
97*d415bd75Srobert     Init.insert(ConstantExpr::getPointerBitCastOrAddrSpaceCast(V, ArrayEltTy));
9809467b48Spatrick 
9909467b48Spatrick   if (Init.empty())
10009467b48Spatrick     return;
10109467b48Spatrick 
102*d415bd75Srobert   ArrayType *ATy = ArrayType::get(ArrayEltTy, Init.size());
10309467b48Spatrick   GV = new llvm::GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage,
104*d415bd75Srobert                                 ConstantArray::get(ATy, Init.getArrayRef()),
105*d415bd75Srobert                                 Name);
10609467b48Spatrick   GV->setSection("llvm.metadata");
10709467b48Spatrick }
10809467b48Spatrick 
appendToUsed(Module & M,ArrayRef<GlobalValue * > Values)10909467b48Spatrick void llvm::appendToUsed(Module &M, ArrayRef<GlobalValue *> Values) {
11009467b48Spatrick   appendToUsedList(M, "llvm.used", Values);
11109467b48Spatrick }
11209467b48Spatrick 
appendToCompilerUsed(Module & M,ArrayRef<GlobalValue * > Values)11309467b48Spatrick void llvm::appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values) {
11409467b48Spatrick   appendToUsedList(M, "llvm.compiler.used", Values);
11509467b48Spatrick }
11609467b48Spatrick 
removeFromUsedList(Module & M,StringRef Name,function_ref<bool (Constant *)> ShouldRemove)117*d415bd75Srobert static void removeFromUsedList(Module &M, StringRef Name,
118*d415bd75Srobert                                function_ref<bool(Constant *)> ShouldRemove) {
119*d415bd75Srobert   GlobalVariable *GV = M.getNamedGlobal(Name);
120*d415bd75Srobert   if (!GV)
121*d415bd75Srobert     return;
122*d415bd75Srobert 
123*d415bd75Srobert   SmallSetVector<Constant *, 16> Init;
124*d415bd75Srobert   collectUsedGlobals(GV, Init);
125*d415bd75Srobert 
126*d415bd75Srobert   Type *ArrayEltTy = cast<ArrayType>(GV->getValueType())->getElementType();
127*d415bd75Srobert 
128*d415bd75Srobert   SmallVector<Constant *, 16> NewInit;
129*d415bd75Srobert   for (Constant *MaybeRemoved : Init) {
130*d415bd75Srobert     if (!ShouldRemove(MaybeRemoved->stripPointerCasts()))
131*d415bd75Srobert       NewInit.push_back(MaybeRemoved);
132*d415bd75Srobert   }
133*d415bd75Srobert 
134*d415bd75Srobert   if (!NewInit.empty()) {
135*d415bd75Srobert     ArrayType *ATy = ArrayType::get(ArrayEltTy, NewInit.size());
136*d415bd75Srobert     GlobalVariable *NewGV =
137*d415bd75Srobert         new GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage,
138*d415bd75Srobert                            ConstantArray::get(ATy, NewInit), "", GV,
139*d415bd75Srobert                            GV->getThreadLocalMode(), GV->getAddressSpace());
140*d415bd75Srobert     NewGV->setSection(GV->getSection());
141*d415bd75Srobert     NewGV->takeName(GV);
142*d415bd75Srobert   }
143*d415bd75Srobert 
144*d415bd75Srobert   GV->eraseFromParent();
145*d415bd75Srobert }
146*d415bd75Srobert 
removeFromUsedLists(Module & M,function_ref<bool (Constant *)> ShouldRemove)147*d415bd75Srobert void llvm::removeFromUsedLists(Module &M,
148*d415bd75Srobert                                function_ref<bool(Constant *)> ShouldRemove) {
149*d415bd75Srobert   removeFromUsedList(M, "llvm.used", ShouldRemove);
150*d415bd75Srobert   removeFromUsedList(M, "llvm.compiler.used", ShouldRemove);
151*d415bd75Srobert }
152*d415bd75Srobert 
setKCFIType(Module & M,Function & F,StringRef MangledType)153*d415bd75Srobert void llvm::setKCFIType(Module &M, Function &F, StringRef MangledType) {
154*d415bd75Srobert   if (!M.getModuleFlag("kcfi"))
155*d415bd75Srobert     return;
156*d415bd75Srobert   // Matches CodeGenModule::CreateKCFITypeId in Clang.
157*d415bd75Srobert   LLVMContext &Ctx = M.getContext();
158*d415bd75Srobert   MDBuilder MDB(Ctx);
159*d415bd75Srobert   F.setMetadata(
160*d415bd75Srobert       LLVMContext::MD_kcfi_type,
161*d415bd75Srobert       MDNode::get(Ctx, MDB.createConstant(ConstantInt::get(
162*d415bd75Srobert                            Type::getInt32Ty(Ctx),
163*d415bd75Srobert                            static_cast<uint32_t>(xxHash64(MangledType))))));
164*d415bd75Srobert   // If the module was compiled with -fpatchable-function-entry, ensure
165*d415bd75Srobert   // we use the same patchable-function-prefix.
166*d415bd75Srobert   if (auto *MD = mdconst::extract_or_null<ConstantInt>(
167*d415bd75Srobert           M.getModuleFlag("kcfi-offset"))) {
168*d415bd75Srobert     if (unsigned Offset = MD->getZExtValue())
169*d415bd75Srobert       F.addFnAttr("patchable-function-prefix", std::to_string(Offset));
170*d415bd75Srobert   }
171*d415bd75Srobert }
172*d415bd75Srobert 
declareSanitizerInitFunction(Module & M,StringRef InitName,ArrayRef<Type * > InitArgTypes,bool Weak)173*d415bd75Srobert FunctionCallee llvm::declareSanitizerInitFunction(Module &M, StringRef InitName,
174*d415bd75Srobert                                                   ArrayRef<Type *> InitArgTypes,
175*d415bd75Srobert                                                   bool Weak) {
17609467b48Spatrick   assert(!InitName.empty() && "Expected init function name");
177*d415bd75Srobert   auto *VoidTy = Type::getVoidTy(M.getContext());
178*d415bd75Srobert   auto *FnTy = FunctionType::get(VoidTy, InitArgTypes, false);
179*d415bd75Srobert   auto FnCallee = M.getOrInsertFunction(InitName, FnTy);
180*d415bd75Srobert   auto *Fn = cast<Function>(FnCallee.getCallee());
181*d415bd75Srobert   if (Weak && Fn->isDeclaration())
182*d415bd75Srobert     Fn->setLinkage(Function::ExternalWeakLinkage);
183*d415bd75Srobert   return FnCallee;
18409467b48Spatrick }
18509467b48Spatrick 
createSanitizerCtor(Module & M,StringRef CtorName)186097a140dSpatrick Function *llvm::createSanitizerCtor(Module &M, StringRef CtorName) {
18773471bf0Spatrick   Function *Ctor = Function::createWithDefaultAttr(
188097a140dSpatrick       FunctionType::get(Type::getVoidTy(M.getContext()), false),
189*d415bd75Srobert       GlobalValue::InternalLinkage, M.getDataLayout().getProgramAddressSpace(),
190*d415bd75Srobert       CtorName, &M);
191*d415bd75Srobert   Ctor->addFnAttr(Attribute::NoUnwind);
192*d415bd75Srobert   setKCFIType(M, *Ctor, "_ZTSFvvE"); // void (*)(void)
193097a140dSpatrick   BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor);
194097a140dSpatrick   ReturnInst::Create(M.getContext(), CtorBB);
19573471bf0Spatrick   // Ensure Ctor cannot be discarded, even if in a comdat.
19673471bf0Spatrick   appendToUsed(M, {Ctor});
197097a140dSpatrick   return Ctor;
198097a140dSpatrick }
199097a140dSpatrick 
createSanitizerCtorAndInitFunctions(Module & M,StringRef CtorName,StringRef InitName,ArrayRef<Type * > InitArgTypes,ArrayRef<Value * > InitArgs,StringRef VersionCheckName,bool Weak)20009467b48Spatrick std::pair<Function *, FunctionCallee> llvm::createSanitizerCtorAndInitFunctions(
20109467b48Spatrick     Module &M, StringRef CtorName, StringRef InitName,
20209467b48Spatrick     ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
203*d415bd75Srobert     StringRef VersionCheckName, bool Weak) {
20409467b48Spatrick   assert(!InitName.empty() && "Expected init function name");
20509467b48Spatrick   assert(InitArgs.size() == InitArgTypes.size() &&
20609467b48Spatrick          "Sanitizer's init function expects different number of arguments");
20709467b48Spatrick   FunctionCallee InitFunction =
208*d415bd75Srobert       declareSanitizerInitFunction(M, InitName, InitArgTypes, Weak);
209097a140dSpatrick   Function *Ctor = createSanitizerCtor(M, CtorName);
210*d415bd75Srobert   IRBuilder<> IRB(M.getContext());
211*d415bd75Srobert 
212*d415bd75Srobert   BasicBlock *RetBB = &Ctor->getEntryBlock();
213*d415bd75Srobert   if (Weak) {
214*d415bd75Srobert     RetBB->setName("ret");
215*d415bd75Srobert     auto *EntryBB = BasicBlock::Create(M.getContext(), "entry", Ctor, RetBB);
216*d415bd75Srobert     auto *CallInitBB =
217*d415bd75Srobert         BasicBlock::Create(M.getContext(), "callfunc", Ctor, RetBB);
218*d415bd75Srobert     auto *InitFn = cast<Function>(InitFunction.getCallee());
219*d415bd75Srobert     auto *InitFnPtr =
220*d415bd75Srobert         PointerType::get(InitFn->getType(), InitFn->getAddressSpace());
221*d415bd75Srobert     IRB.SetInsertPoint(EntryBB);
222*d415bd75Srobert     Value *InitNotNull =
223*d415bd75Srobert         IRB.CreateICmpNE(InitFn, ConstantPointerNull::get(InitFnPtr));
224*d415bd75Srobert     IRB.CreateCondBr(InitNotNull, CallInitBB, RetBB);
225*d415bd75Srobert     IRB.SetInsertPoint(CallInitBB);
226*d415bd75Srobert   } else {
227*d415bd75Srobert     IRB.SetInsertPoint(RetBB->getTerminator());
228*d415bd75Srobert   }
229*d415bd75Srobert 
23009467b48Spatrick   IRB.CreateCall(InitFunction, InitArgs);
23109467b48Spatrick   if (!VersionCheckName.empty()) {
23209467b48Spatrick     FunctionCallee VersionCheckFunction = M.getOrInsertFunction(
23309467b48Spatrick         VersionCheckName, FunctionType::get(IRB.getVoidTy(), {}, false),
23409467b48Spatrick         AttributeList());
23509467b48Spatrick     IRB.CreateCall(VersionCheckFunction, {});
23609467b48Spatrick   }
237*d415bd75Srobert 
238*d415bd75Srobert   if (Weak)
239*d415bd75Srobert     IRB.CreateBr(RetBB);
240*d415bd75Srobert 
24109467b48Spatrick   return std::make_pair(Ctor, InitFunction);
24209467b48Spatrick }
24309467b48Spatrick 
24409467b48Spatrick 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)24509467b48Spatrick llvm::getOrCreateSanitizerCtorAndInitFunctions(
24609467b48Spatrick     Module &M, StringRef CtorName, StringRef InitName,
24709467b48Spatrick     ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
24809467b48Spatrick     function_ref<void(Function *, FunctionCallee)> FunctionsCreatedCallback,
249*d415bd75Srobert     StringRef VersionCheckName, bool Weak) {
25009467b48Spatrick   assert(!CtorName.empty() && "Expected ctor function name");
25109467b48Spatrick 
25209467b48Spatrick   if (Function *Ctor = M.getFunction(CtorName))
25309467b48Spatrick     // FIXME: Sink this logic into the module, similar to the handling of
25409467b48Spatrick     // globals. This will make moving to a concurrent model much easier.
255*d415bd75Srobert     if (Ctor->arg_empty() ||
25609467b48Spatrick         Ctor->getReturnType() == Type::getVoidTy(M.getContext()))
257*d415bd75Srobert       return {Ctor,
258*d415bd75Srobert               declareSanitizerInitFunction(M, InitName, InitArgTypes, Weak)};
25909467b48Spatrick 
26009467b48Spatrick   Function *Ctor;
26109467b48Spatrick   FunctionCallee InitFunction;
26209467b48Spatrick   std::tie(Ctor, InitFunction) = llvm::createSanitizerCtorAndInitFunctions(
263*d415bd75Srobert       M, CtorName, InitName, InitArgTypes, InitArgs, VersionCheckName, Weak);
26409467b48Spatrick   FunctionsCreatedCallback(Ctor, InitFunction);
26509467b48Spatrick   return std::make_pair(Ctor, InitFunction);
26609467b48Spatrick }
26709467b48Spatrick 
filterDeadComdatFunctions(SmallVectorImpl<Function * > & DeadComdatFunctions)26809467b48Spatrick void llvm::filterDeadComdatFunctions(
269*d415bd75Srobert     SmallVectorImpl<Function *> &DeadComdatFunctions) {
270*d415bd75Srobert   SmallPtrSet<Function *, 32> MaybeDeadFunctions;
271*d415bd75Srobert   SmallPtrSet<Comdat *, 32> MaybeDeadComdats;
27209467b48Spatrick   for (Function *F : DeadComdatFunctions) {
273*d415bd75Srobert     MaybeDeadFunctions.insert(F);
274*d415bd75Srobert     if (Comdat *C = F->getComdat())
275*d415bd75Srobert       MaybeDeadComdats.insert(C);
276*d415bd75Srobert   }
277*d415bd75Srobert 
278*d415bd75Srobert   // Find comdats for which all users are dead now.
279*d415bd75Srobert   SmallPtrSet<Comdat *, 32> DeadComdats;
280*d415bd75Srobert   for (Comdat *C : MaybeDeadComdats) {
281*d415bd75Srobert     auto IsUserDead = [&](GlobalObject *GO) {
282*d415bd75Srobert       auto *F = dyn_cast<Function>(GO);
283*d415bd75Srobert       return F && MaybeDeadFunctions.contains(F);
284*d415bd75Srobert     };
285*d415bd75Srobert     if (all_of(C->getUsers(), IsUserDead))
286*d415bd75Srobert       DeadComdats.insert(C);
287*d415bd75Srobert   }
288*d415bd75Srobert 
289*d415bd75Srobert   // Only keep functions which have no comdat or a dead comdat.
290*d415bd75Srobert   erase_if(DeadComdatFunctions, [&](Function *F) {
29109467b48Spatrick     Comdat *C = F->getComdat();
292*d415bd75Srobert     return C && !DeadComdats.contains(C);
29309467b48Spatrick   });
29409467b48Spatrick }
29509467b48Spatrick 
getUniqueModuleId(Module * M)29609467b48Spatrick std::string llvm::getUniqueModuleId(Module *M) {
29709467b48Spatrick   MD5 Md5;
29809467b48Spatrick   bool ExportsSymbols = false;
29909467b48Spatrick   auto AddGlobal = [&](GlobalValue &GV) {
30009467b48Spatrick     if (GV.isDeclaration() || GV.getName().startswith("llvm.") ||
30109467b48Spatrick         !GV.hasExternalLinkage() || GV.hasComdat())
30209467b48Spatrick       return;
30309467b48Spatrick     ExportsSymbols = true;
30409467b48Spatrick     Md5.update(GV.getName());
30509467b48Spatrick     Md5.update(ArrayRef<uint8_t>{0});
30609467b48Spatrick   };
30709467b48Spatrick 
30809467b48Spatrick   for (auto &F : *M)
30909467b48Spatrick     AddGlobal(F);
31009467b48Spatrick   for (auto &GV : M->globals())
31109467b48Spatrick     AddGlobal(GV);
31209467b48Spatrick   for (auto &GA : M->aliases())
31309467b48Spatrick     AddGlobal(GA);
31409467b48Spatrick   for (auto &IF : M->ifuncs())
31509467b48Spatrick     AddGlobal(IF);
31609467b48Spatrick 
31709467b48Spatrick   if (!ExportsSymbols)
31809467b48Spatrick     return "";
31909467b48Spatrick 
32009467b48Spatrick   MD5::MD5Result R;
32109467b48Spatrick   Md5.final(R);
32209467b48Spatrick 
32309467b48Spatrick   SmallString<32> Str;
32409467b48Spatrick   MD5::stringifyResult(R, Str);
32573471bf0Spatrick   return ("." + Str).str();
32609467b48Spatrick }
32709467b48Spatrick 
setVectorVariantNames(CallInst * CI,ArrayRef<std::string> VariantMappings)328*d415bd75Srobert void VFABI::setVectorVariantNames(CallInst *CI,
329*d415bd75Srobert                                   ArrayRef<std::string> VariantMappings) {
33009467b48Spatrick   if (VariantMappings.empty())
33109467b48Spatrick     return;
33209467b48Spatrick 
33309467b48Spatrick   SmallString<256> Buffer;
33409467b48Spatrick   llvm::raw_svector_ostream Out(Buffer);
33509467b48Spatrick   for (const std::string &VariantMapping : VariantMappings)
33609467b48Spatrick     Out << VariantMapping << ",";
33709467b48Spatrick   // Get rid of the trailing ','.
33809467b48Spatrick   assert(!Buffer.str().empty() && "Must have at least one char.");
33909467b48Spatrick   Buffer.pop_back();
34009467b48Spatrick 
34109467b48Spatrick   Module *M = CI->getModule();
34209467b48Spatrick #ifndef NDEBUG
34309467b48Spatrick   for (const std::string &VariantMapping : VariantMappings) {
344097a140dSpatrick     LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << VariantMapping << "'\n");
345*d415bd75Srobert     std::optional<VFInfo> VI = VFABI::tryDemangleForVFABI(VariantMapping, *M);
346*d415bd75Srobert     assert(VI && "Cannot add an invalid VFABI name.");
347*d415bd75Srobert     assert(M->getNamedValue(VI->VectorName) &&
34809467b48Spatrick            "Cannot add variant to attribute: "
34909467b48Spatrick            "vector function declaration is missing.");
35009467b48Spatrick   }
35109467b48Spatrick #endif
352*d415bd75Srobert   CI->addFnAttr(
35309467b48Spatrick       Attribute::get(M->getContext(), MappingsAttrName, Buffer.str()));
35409467b48Spatrick }
355*d415bd75Srobert 
embedBufferInModule(Module & M,MemoryBufferRef Buf,StringRef SectionName,Align Alignment)356*d415bd75Srobert void llvm::embedBufferInModule(Module &M, MemoryBufferRef Buf,
357*d415bd75Srobert                                StringRef SectionName, Align Alignment) {
358*d415bd75Srobert   // Embed the memory buffer into the module.
359*d415bd75Srobert   Constant *ModuleConstant = ConstantDataArray::get(
360*d415bd75Srobert       M.getContext(), ArrayRef(Buf.getBufferStart(), Buf.getBufferSize()));
361*d415bd75Srobert   GlobalVariable *GV = new GlobalVariable(
362*d415bd75Srobert       M, ModuleConstant->getType(), true, GlobalValue::PrivateLinkage,
363*d415bd75Srobert       ModuleConstant, "llvm.embedded.object");
364*d415bd75Srobert   GV->setSection(SectionName);
365*d415bd75Srobert   GV->setAlignment(Alignment);
366*d415bd75Srobert 
367*d415bd75Srobert   LLVMContext &Ctx = M.getContext();
368*d415bd75Srobert   NamedMDNode *MD = M.getOrInsertNamedMetadata("llvm.embedded.objects");
369*d415bd75Srobert   Metadata *MDVals[] = {ConstantAsMetadata::get(GV),
370*d415bd75Srobert                         MDString::get(Ctx, SectionName)};
371*d415bd75Srobert 
372*d415bd75Srobert   MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
373*d415bd75Srobert   GV->setMetadata(LLVMContext::MD_exclude, llvm::MDNode::get(Ctx, {}));
374*d415bd75Srobert 
375*d415bd75Srobert   appendToCompilerUsed(M, GV);
376*d415bd75Srobert }
377*d415bd75Srobert 
lowerGlobalIFuncUsersAsGlobalCtor(Module & M,ArrayRef<GlobalIFunc * > FilteredIFuncsToLower)378*d415bd75Srobert bool llvm::lowerGlobalIFuncUsersAsGlobalCtor(
379*d415bd75Srobert     Module &M, ArrayRef<GlobalIFunc *> FilteredIFuncsToLower) {
380*d415bd75Srobert   SmallVector<GlobalIFunc *, 32> AllIFuncs;
381*d415bd75Srobert   ArrayRef<GlobalIFunc *> IFuncsToLower = FilteredIFuncsToLower;
382*d415bd75Srobert   if (FilteredIFuncsToLower.empty()) { // Default to lowering all ifuncs
383*d415bd75Srobert     for (GlobalIFunc &GI : M.ifuncs())
384*d415bd75Srobert       AllIFuncs.push_back(&GI);
385*d415bd75Srobert     IFuncsToLower = AllIFuncs;
386*d415bd75Srobert   }
387*d415bd75Srobert 
388*d415bd75Srobert   bool UnhandledUsers = false;
389*d415bd75Srobert   LLVMContext &Ctx = M.getContext();
390*d415bd75Srobert   const DataLayout &DL = M.getDataLayout();
391*d415bd75Srobert 
392*d415bd75Srobert   PointerType *TableEntryTy =
393*d415bd75Srobert       Ctx.supportsTypedPointers()
394*d415bd75Srobert           ? PointerType::get(Type::getInt8Ty(Ctx), DL.getProgramAddressSpace())
395*d415bd75Srobert           : PointerType::get(Ctx, DL.getProgramAddressSpace());
396*d415bd75Srobert 
397*d415bd75Srobert   ArrayType *FuncPtrTableTy =
398*d415bd75Srobert       ArrayType::get(TableEntryTy, IFuncsToLower.size());
399*d415bd75Srobert 
400*d415bd75Srobert   Align PtrAlign = DL.getABITypeAlign(TableEntryTy);
401*d415bd75Srobert 
402*d415bd75Srobert   // Create a global table of function pointers we'll initialize in a global
403*d415bd75Srobert   // constructor.
404*d415bd75Srobert   auto *FuncPtrTable = new GlobalVariable(
405*d415bd75Srobert       M, FuncPtrTableTy, false, GlobalValue::InternalLinkage,
406*d415bd75Srobert       PoisonValue::get(FuncPtrTableTy), "", nullptr,
407*d415bd75Srobert       GlobalVariable::NotThreadLocal, DL.getDefaultGlobalsAddressSpace());
408*d415bd75Srobert   FuncPtrTable->setAlignment(PtrAlign);
409*d415bd75Srobert 
410*d415bd75Srobert   // Create a function to initialize the function pointer table.
411*d415bd75Srobert   Function *NewCtor = Function::Create(
412*d415bd75Srobert       FunctionType::get(Type::getVoidTy(Ctx), false), Function::InternalLinkage,
413*d415bd75Srobert       DL.getProgramAddressSpace(), "", &M);
414*d415bd75Srobert 
415*d415bd75Srobert   BasicBlock *BB = BasicBlock::Create(Ctx, "", NewCtor);
416*d415bd75Srobert   IRBuilder<> InitBuilder(BB);
417*d415bd75Srobert 
418*d415bd75Srobert   size_t TableIndex = 0;
419*d415bd75Srobert   for (GlobalIFunc *GI : IFuncsToLower) {
420*d415bd75Srobert     Function *ResolvedFunction = GI->getResolverFunction();
421*d415bd75Srobert 
422*d415bd75Srobert     // We don't know what to pass to a resolver function taking arguments
423*d415bd75Srobert     //
424*d415bd75Srobert     // FIXME: Is this even valid? clang and gcc don't complain but this
425*d415bd75Srobert     // probably should be invalid IR. We could just pass through undef.
426*d415bd75Srobert     if (!std::empty(ResolvedFunction->getFunctionType()->params())) {
427*d415bd75Srobert       LLVM_DEBUG(dbgs() << "Not lowering ifunc resolver function "
428*d415bd75Srobert                         << ResolvedFunction->getName() << " with parameters\n");
429*d415bd75Srobert       UnhandledUsers = true;
430*d415bd75Srobert       continue;
431*d415bd75Srobert     }
432*d415bd75Srobert 
433*d415bd75Srobert     // Initialize the function pointer table.
434*d415bd75Srobert     CallInst *ResolvedFunc = InitBuilder.CreateCall(ResolvedFunction);
435*d415bd75Srobert     Value *Casted = InitBuilder.CreatePointerCast(ResolvedFunc, TableEntryTy);
436*d415bd75Srobert     Constant *GEP = cast<Constant>(InitBuilder.CreateConstInBoundsGEP2_32(
437*d415bd75Srobert         FuncPtrTableTy, FuncPtrTable, 0, TableIndex++));
438*d415bd75Srobert     InitBuilder.CreateAlignedStore(Casted, GEP, PtrAlign);
439*d415bd75Srobert 
440*d415bd75Srobert     // Update all users to load a pointer from the global table.
441*d415bd75Srobert     for (User *User : make_early_inc_range(GI->users())) {
442*d415bd75Srobert       Instruction *UserInst = dyn_cast<Instruction>(User);
443*d415bd75Srobert       if (!UserInst) {
444*d415bd75Srobert         // TODO: Should handle constantexpr casts in user instructions. Probably
445*d415bd75Srobert         // can't do much about constant initializers.
446*d415bd75Srobert         UnhandledUsers = true;
447*d415bd75Srobert         continue;
448*d415bd75Srobert       }
449*d415bd75Srobert 
450*d415bd75Srobert       IRBuilder<> UseBuilder(UserInst);
451*d415bd75Srobert       LoadInst *ResolvedTarget =
452*d415bd75Srobert           UseBuilder.CreateAlignedLoad(TableEntryTy, GEP, PtrAlign);
453*d415bd75Srobert       Value *ResolvedCast =
454*d415bd75Srobert           UseBuilder.CreatePointerCast(ResolvedTarget, GI->getType());
455*d415bd75Srobert       UserInst->replaceUsesOfWith(GI, ResolvedCast);
456*d415bd75Srobert     }
457*d415bd75Srobert 
458*d415bd75Srobert     // If we handled all users, erase the ifunc.
459*d415bd75Srobert     if (GI->use_empty())
460*d415bd75Srobert       GI->eraseFromParent();
461*d415bd75Srobert   }
462*d415bd75Srobert 
463*d415bd75Srobert   InitBuilder.CreateRetVoid();
464*d415bd75Srobert 
465*d415bd75Srobert   PointerType *ConstantDataTy = Ctx.supportsTypedPointers()
466*d415bd75Srobert                                     ? PointerType::get(Type::getInt8Ty(Ctx), 0)
467*d415bd75Srobert                                     : PointerType::get(Ctx, 0);
468*d415bd75Srobert 
469*d415bd75Srobert   // TODO: Is this the right priority? Probably should be before any other
470*d415bd75Srobert   // constructors?
471*d415bd75Srobert   const int Priority = 10;
472*d415bd75Srobert   appendToGlobalCtors(M, NewCtor, Priority,
473*d415bd75Srobert                       ConstantPointerNull::get(ConstantDataTy));
474*d415bd75Srobert   return UnhandledUsers;
475*d415bd75Srobert }
476