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