1 //===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This family of functions perform manipulations on Modules.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "llvm/Transforms/Utils/ModuleUtils.h"
14 #include "llvm/Analysis/VectorUtils.h"
15 #include "llvm/IR/DerivedTypes.h"
16 #include "llvm/IR/Function.h"
17 #include "llvm/IR/IRBuilder.h"
18 #include "llvm/IR/Module.h"
19 #include "llvm/Support/raw_ostream.h"
20 using namespace llvm;
21
22 #define DEBUG_TYPE "moduleutils"
23
appendToGlobalArray(const char * Array,Module & M,Function * F,int Priority,Constant * Data)24 static void appendToGlobalArray(const char *Array, Module &M, Function *F,
25 int Priority, Constant *Data) {
26 IRBuilder<> IRB(M.getContext());
27 FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false);
28
29 // Get the current set of static global constructors and add the new ctor
30 // to the list.
31 SmallVector<Constant *, 16> CurrentCtors;
32 StructType *EltTy = StructType::get(
33 IRB.getInt32Ty(), PointerType::getUnqual(FnTy), IRB.getInt8PtrTy());
34 if (GlobalVariable *GVCtor = M.getNamedGlobal(Array)) {
35 if (Constant *Init = GVCtor->getInitializer()) {
36 unsigned n = Init->getNumOperands();
37 CurrentCtors.reserve(n + 1);
38 for (unsigned i = 0; i != n; ++i)
39 CurrentCtors.push_back(cast<Constant>(Init->getOperand(i)));
40 }
41 GVCtor->eraseFromParent();
42 }
43
44 // Build a 3 field global_ctor entry. We don't take a comdat key.
45 Constant *CSVals[3];
46 CSVals[0] = IRB.getInt32(Priority);
47 CSVals[1] = F;
48 CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getInt8PtrTy())
49 : Constant::getNullValue(IRB.getInt8PtrTy());
50 Constant *RuntimeCtorInit =
51 ConstantStruct::get(EltTy, makeArrayRef(CSVals, EltTy->getNumElements()));
52
53 CurrentCtors.push_back(RuntimeCtorInit);
54
55 // Create a new initializer.
56 ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size());
57 Constant *NewInit = ConstantArray::get(AT, CurrentCtors);
58
59 // Create the new global variable and replace all uses of
60 // the old global variable with the new one.
61 (void)new GlobalVariable(M, NewInit->getType(), false,
62 GlobalValue::AppendingLinkage, NewInit, Array);
63 }
64
appendToGlobalCtors(Module & M,Function * F,int Priority,Constant * Data)65 void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data) {
66 appendToGlobalArray("llvm.global_ctors", M, F, Priority, Data);
67 }
68
appendToGlobalDtors(Module & M,Function * F,int Priority,Constant * Data)69 void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data) {
70 appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data);
71 }
72
appendToUsedList(Module & M,StringRef Name,ArrayRef<GlobalValue * > Values)73 static void appendToUsedList(Module &M, StringRef Name, ArrayRef<GlobalValue *> Values) {
74 GlobalVariable *GV = M.getGlobalVariable(Name);
75 SmallPtrSet<Constant *, 16> InitAsSet;
76 SmallVector<Constant *, 16> Init;
77 if (GV) {
78 if (GV->hasInitializer()) {
79 auto *CA = cast<ConstantArray>(GV->getInitializer());
80 for (auto &Op : CA->operands()) {
81 Constant *C = cast_or_null<Constant>(Op);
82 if (InitAsSet.insert(C).second)
83 Init.push_back(C);
84 }
85 }
86 GV->eraseFromParent();
87 }
88
89 Type *Int8PtrTy = llvm::Type::getInt8PtrTy(M.getContext());
90 for (auto *V : Values) {
91 Constant *C = ConstantExpr::getPointerBitCastOrAddrSpaceCast(V, Int8PtrTy);
92 if (InitAsSet.insert(C).second)
93 Init.push_back(C);
94 }
95
96 if (Init.empty())
97 return;
98
99 ArrayType *ATy = ArrayType::get(Int8PtrTy, Init.size());
100 GV = new llvm::GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage,
101 ConstantArray::get(ATy, Init), Name);
102 GV->setSection("llvm.metadata");
103 }
104
appendToUsed(Module & M,ArrayRef<GlobalValue * > Values)105 void llvm::appendToUsed(Module &M, ArrayRef<GlobalValue *> Values) {
106 appendToUsedList(M, "llvm.used", Values);
107 }
108
appendToCompilerUsed(Module & M,ArrayRef<GlobalValue * > Values)109 void llvm::appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values) {
110 appendToUsedList(M, "llvm.compiler.used", Values);
111 }
112
113 FunctionCallee
declareSanitizerInitFunction(Module & M,StringRef InitName,ArrayRef<Type * > InitArgTypes)114 llvm::declareSanitizerInitFunction(Module &M, StringRef InitName,
115 ArrayRef<Type *> InitArgTypes) {
116 assert(!InitName.empty() && "Expected init function name");
117 return M.getOrInsertFunction(
118 InitName,
119 FunctionType::get(Type::getVoidTy(M.getContext()), InitArgTypes, false),
120 AttributeList());
121 }
122
createSanitizerCtor(Module & M,StringRef CtorName)123 Function *llvm::createSanitizerCtor(Module &M, StringRef CtorName) {
124 Function *Ctor = Function::createWithDefaultAttr(
125 FunctionType::get(Type::getVoidTy(M.getContext()), false),
126 GlobalValue::InternalLinkage, 0, CtorName, &M);
127 Ctor->addFnAttr(Attribute::NoUnwind);
128 BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor);
129 ReturnInst::Create(M.getContext(), CtorBB);
130 // Ensure Ctor cannot be discarded, even if in a comdat.
131 appendToUsed(M, {Ctor});
132 return Ctor;
133 }
134
createSanitizerCtorAndInitFunctions(Module & M,StringRef CtorName,StringRef InitName,ArrayRef<Type * > InitArgTypes,ArrayRef<Value * > InitArgs,StringRef VersionCheckName)135 std::pair<Function *, FunctionCallee> llvm::createSanitizerCtorAndInitFunctions(
136 Module &M, StringRef CtorName, StringRef InitName,
137 ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
138 StringRef VersionCheckName) {
139 assert(!InitName.empty() && "Expected init function name");
140 assert(InitArgs.size() == InitArgTypes.size() &&
141 "Sanitizer's init function expects different number of arguments");
142 FunctionCallee InitFunction =
143 declareSanitizerInitFunction(M, InitName, InitArgTypes);
144 Function *Ctor = createSanitizerCtor(M, CtorName);
145 IRBuilder<> IRB(Ctor->getEntryBlock().getTerminator());
146 IRB.CreateCall(InitFunction, InitArgs);
147 if (!VersionCheckName.empty()) {
148 FunctionCallee VersionCheckFunction = M.getOrInsertFunction(
149 VersionCheckName, FunctionType::get(IRB.getVoidTy(), {}, false),
150 AttributeList());
151 IRB.CreateCall(VersionCheckFunction, {});
152 }
153 return std::make_pair(Ctor, InitFunction);
154 }
155
156 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)157 llvm::getOrCreateSanitizerCtorAndInitFunctions(
158 Module &M, StringRef CtorName, StringRef InitName,
159 ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs,
160 function_ref<void(Function *, FunctionCallee)> FunctionsCreatedCallback,
161 StringRef VersionCheckName) {
162 assert(!CtorName.empty() && "Expected ctor function name");
163
164 if (Function *Ctor = M.getFunction(CtorName))
165 // FIXME: Sink this logic into the module, similar to the handling of
166 // globals. This will make moving to a concurrent model much easier.
167 if (Ctor->arg_empty() ||
168 Ctor->getReturnType() == Type::getVoidTy(M.getContext()))
169 return {Ctor, declareSanitizerInitFunction(M, InitName, InitArgTypes)};
170
171 Function *Ctor;
172 FunctionCallee InitFunction;
173 std::tie(Ctor, InitFunction) = llvm::createSanitizerCtorAndInitFunctions(
174 M, CtorName, InitName, InitArgTypes, InitArgs, VersionCheckName);
175 FunctionsCreatedCallback(Ctor, InitFunction);
176 return std::make_pair(Ctor, InitFunction);
177 }
178
filterDeadComdatFunctions(SmallVectorImpl<Function * > & DeadComdatFunctions)179 void llvm::filterDeadComdatFunctions(
180 SmallVectorImpl<Function *> &DeadComdatFunctions) {
181 SmallPtrSet<Function *, 32> MaybeDeadFunctions;
182 SmallPtrSet<Comdat *, 32> MaybeDeadComdats;
183 for (Function *F : DeadComdatFunctions) {
184 MaybeDeadFunctions.insert(F);
185 if (Comdat *C = F->getComdat())
186 MaybeDeadComdats.insert(C);
187 }
188
189 // Find comdats for which all users are dead now.
190 SmallPtrSet<Comdat *, 32> DeadComdats;
191 for (Comdat *C : MaybeDeadComdats) {
192 auto IsUserDead = [&](GlobalObject *GO) {
193 auto *F = dyn_cast<Function>(GO);
194 return F && MaybeDeadFunctions.contains(F);
195 };
196 if (all_of(C->getUsers(), IsUserDead))
197 DeadComdats.insert(C);
198 }
199
200 // Only keep functions which have no comdat or a dead comdat.
201 erase_if(DeadComdatFunctions, [&](Function *F) {
202 Comdat *C = F->getComdat();
203 return C && !DeadComdats.contains(C);
204 });
205 }
206
getUniqueModuleId(Module * M)207 std::string llvm::getUniqueModuleId(Module *M) {
208 MD5 Md5;
209 bool ExportsSymbols = false;
210 auto AddGlobal = [&](GlobalValue &GV) {
211 if (GV.isDeclaration() || GV.getName().startswith("llvm.") ||
212 !GV.hasExternalLinkage() || GV.hasComdat())
213 return;
214 ExportsSymbols = true;
215 Md5.update(GV.getName());
216 Md5.update(ArrayRef<uint8_t>{0});
217 };
218
219 for (auto &F : *M)
220 AddGlobal(F);
221 for (auto &GV : M->globals())
222 AddGlobal(GV);
223 for (auto &GA : M->aliases())
224 AddGlobal(GA);
225 for (auto &IF : M->ifuncs())
226 AddGlobal(IF);
227
228 if (!ExportsSymbols)
229 return "";
230
231 MD5::MD5Result R;
232 Md5.final(R);
233
234 SmallString<32> Str;
235 MD5::stringifyResult(R, Str);
236 return ("." + Str).str();
237 }
238
setVectorVariantNames(CallInst * CI,ArrayRef<std::string> VariantMappings)239 void VFABI::setVectorVariantNames(CallInst *CI,
240 ArrayRef<std::string> VariantMappings) {
241 if (VariantMappings.empty())
242 return;
243
244 SmallString<256> Buffer;
245 llvm::raw_svector_ostream Out(Buffer);
246 for (const std::string &VariantMapping : VariantMappings)
247 Out << VariantMapping << ",";
248 // Get rid of the trailing ','.
249 assert(!Buffer.str().empty() && "Must have at least one char.");
250 Buffer.pop_back();
251
252 Module *M = CI->getModule();
253 #ifndef NDEBUG
254 for (const std::string &VariantMapping : VariantMappings) {
255 LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << VariantMapping << "'\n");
256 Optional<VFInfo> VI = VFABI::tryDemangleForVFABI(VariantMapping, *M);
257 assert(VI && "Cannot add an invalid VFABI name.");
258 assert(M->getNamedValue(VI.value().VectorName) &&
259 "Cannot add variant to attribute: "
260 "vector function declaration is missing.");
261 }
262 #endif
263 CI->addFnAttr(
264 Attribute::get(M->getContext(), MappingsAttrName, Buffer.str()));
265 }
266
embedBufferInModule(Module & M,MemoryBufferRef Buf,StringRef SectionName,Align Alignment)267 void llvm::embedBufferInModule(Module &M, MemoryBufferRef Buf,
268 StringRef SectionName, Align Alignment) {
269 // Embed the memory buffer into the module.
270 Constant *ModuleConstant = ConstantDataArray::get(
271 M.getContext(), makeArrayRef(Buf.getBufferStart(), Buf.getBufferSize()));
272 GlobalVariable *GV = new GlobalVariable(
273 M, ModuleConstant->getType(), true, GlobalValue::PrivateLinkage,
274 ModuleConstant, "llvm.embedded.object");
275 GV->setSection(SectionName);
276 GV->setAlignment(Alignment);
277
278 LLVMContext &Ctx = M.getContext();
279 NamedMDNode *MD = M.getOrInsertNamedMetadata("llvm.embedded.objects");
280 Metadata *MDVals[] = {ConstantAsMetadata::get(GV),
281 MDString::get(Ctx, SectionName)};
282
283 MD->addOperand(llvm::MDNode::get(Ctx, MDVals));
284 GV->setMetadata(LLVMContext::MD_exclude, llvm::MDNode::get(Ctx, {}));
285
286 appendToCompilerUsed(M, GV);
287 }
288