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