10b57cec5SDimitry Andric //===-- ModuleUtils.cpp - Functions to manipulate Modules -----------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This family of functions perform manipulations on Modules. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h" 14480093f4SDimitry Andric #include "llvm/Analysis/VectorUtils.h" 15*fe013be4SDimitry Andric #include "llvm/ADT/SmallString.h" 160b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 170b57cec5SDimitry Andric #include "llvm/IR/Function.h" 180b57cec5SDimitry Andric #include "llvm/IR/IRBuilder.h" 19bdd1243dSDimitry Andric #include "llvm/IR/MDBuilder.h" 200b57cec5SDimitry Andric #include "llvm/IR/Module.h" 210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 22bdd1243dSDimitry Andric #include "llvm/Support/xxhash.h" 23*fe013be4SDimitry Andric 240b57cec5SDimitry Andric using namespace llvm; 250b57cec5SDimitry Andric 265ffd83dbSDimitry Andric #define DEBUG_TYPE "moduleutils" 275ffd83dbSDimitry Andric 28bdd1243dSDimitry Andric static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F, 290b57cec5SDimitry Andric int Priority, Constant *Data) { 300b57cec5SDimitry Andric IRBuilder<> IRB(M.getContext()); 310b57cec5SDimitry Andric FunctionType *FnTy = FunctionType::get(IRB.getVoidTy(), false); 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric // Get the current set of static global constructors and add the new ctor 340b57cec5SDimitry Andric // to the list. 350b57cec5SDimitry Andric SmallVector<Constant *, 16> CurrentCtors; 36*fe013be4SDimitry Andric StructType *EltTy; 37bdd1243dSDimitry Andric if (GlobalVariable *GVCtor = M.getNamedGlobal(ArrayName)) { 38*fe013be4SDimitry Andric EltTy = cast<StructType>(GVCtor->getValueType()->getArrayElementType()); 390b57cec5SDimitry Andric if (Constant *Init = GVCtor->getInitializer()) { 400b57cec5SDimitry Andric unsigned n = Init->getNumOperands(); 410b57cec5SDimitry Andric CurrentCtors.reserve(n + 1); 420b57cec5SDimitry Andric for (unsigned i = 0; i != n; ++i) 430b57cec5SDimitry Andric CurrentCtors.push_back(cast<Constant>(Init->getOperand(i))); 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric GVCtor->eraseFromParent(); 46*fe013be4SDimitry Andric } else { 47*fe013be4SDimitry Andric EltTy = StructType::get( 48*fe013be4SDimitry Andric IRB.getInt32Ty(), PointerType::get(FnTy, F->getAddressSpace()), 49*fe013be4SDimitry Andric IRB.getInt8PtrTy()); 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric // Build a 3 field global_ctor entry. We don't take a comdat key. 530b57cec5SDimitry Andric Constant *CSVals[3]; 540b57cec5SDimitry Andric CSVals[0] = IRB.getInt32(Priority); 550b57cec5SDimitry Andric CSVals[1] = F; 560b57cec5SDimitry Andric CSVals[2] = Data ? ConstantExpr::getPointerCast(Data, IRB.getInt8PtrTy()) 570b57cec5SDimitry Andric : Constant::getNullValue(IRB.getInt8PtrTy()); 580b57cec5SDimitry Andric Constant *RuntimeCtorInit = 59bdd1243dSDimitry Andric ConstantStruct::get(EltTy, ArrayRef(CSVals, EltTy->getNumElements())); 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric CurrentCtors.push_back(RuntimeCtorInit); 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric // Create a new initializer. 640b57cec5SDimitry Andric ArrayType *AT = ArrayType::get(EltTy, CurrentCtors.size()); 650b57cec5SDimitry Andric Constant *NewInit = ConstantArray::get(AT, CurrentCtors); 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric // Create the new global variable and replace all uses of 680b57cec5SDimitry Andric // the old global variable with the new one. 690b57cec5SDimitry Andric (void)new GlobalVariable(M, NewInit->getType(), false, 70bdd1243dSDimitry Andric GlobalValue::AppendingLinkage, NewInit, ArrayName); 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric void llvm::appendToGlobalCtors(Module &M, Function *F, int Priority, Constant *Data) { 740b57cec5SDimitry Andric appendToGlobalArray("llvm.global_ctors", M, F, Priority, Data); 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric void llvm::appendToGlobalDtors(Module &M, Function *F, int Priority, Constant *Data) { 780b57cec5SDimitry Andric appendToGlobalArray("llvm.global_dtors", M, F, Priority, Data); 790b57cec5SDimitry Andric } 800b57cec5SDimitry Andric 81bdd1243dSDimitry Andric static void collectUsedGlobals(GlobalVariable *GV, 82bdd1243dSDimitry Andric SmallSetVector<Constant *, 16> &Init) { 83bdd1243dSDimitry Andric if (!GV || !GV->hasInitializer()) 84bdd1243dSDimitry Andric return; 85bdd1243dSDimitry Andric 868bcb0991SDimitry Andric auto *CA = cast<ConstantArray>(GV->getInitializer()); 87bdd1243dSDimitry Andric for (Use &Op : CA->operands()) 88bdd1243dSDimitry Andric Init.insert(cast<Constant>(Op)); 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 91bdd1243dSDimitry Andric static void appendToUsedList(Module &M, StringRef Name, ArrayRef<GlobalValue *> Values) { 92bdd1243dSDimitry Andric GlobalVariable *GV = M.getGlobalVariable(Name); 93bdd1243dSDimitry Andric 94bdd1243dSDimitry Andric SmallSetVector<Constant *, 16> Init; 95bdd1243dSDimitry Andric collectUsedGlobals(GV, Init); 96bdd1243dSDimitry Andric if (GV) 97bdd1243dSDimitry Andric GV->eraseFromParent(); 98bdd1243dSDimitry Andric 99bdd1243dSDimitry Andric Type *ArrayEltTy = llvm::Type::getInt8PtrTy(M.getContext()); 100bdd1243dSDimitry Andric for (auto *V : Values) 101bdd1243dSDimitry Andric Init.insert(ConstantExpr::getPointerBitCastOrAddrSpaceCast(V, ArrayEltTy)); 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric if (Init.empty()) 1040b57cec5SDimitry Andric return; 1050b57cec5SDimitry Andric 106bdd1243dSDimitry Andric ArrayType *ATy = ArrayType::get(ArrayEltTy, Init.size()); 1070b57cec5SDimitry Andric GV = new llvm::GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage, 108bdd1243dSDimitry Andric ConstantArray::get(ATy, Init.getArrayRef()), 109bdd1243dSDimitry Andric Name); 1100b57cec5SDimitry Andric GV->setSection("llvm.metadata"); 1110b57cec5SDimitry Andric } 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric void llvm::appendToUsed(Module &M, ArrayRef<GlobalValue *> Values) { 1140b57cec5SDimitry Andric appendToUsedList(M, "llvm.used", Values); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric void llvm::appendToCompilerUsed(Module &M, ArrayRef<GlobalValue *> Values) { 1180b57cec5SDimitry Andric appendToUsedList(M, "llvm.compiler.used", Values); 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric 121bdd1243dSDimitry Andric static void removeFromUsedList(Module &M, StringRef Name, 122bdd1243dSDimitry Andric function_ref<bool(Constant *)> ShouldRemove) { 123bdd1243dSDimitry Andric GlobalVariable *GV = M.getNamedGlobal(Name); 124bdd1243dSDimitry Andric if (!GV) 125bdd1243dSDimitry Andric return; 126bdd1243dSDimitry Andric 127bdd1243dSDimitry Andric SmallSetVector<Constant *, 16> Init; 128bdd1243dSDimitry Andric collectUsedGlobals(GV, Init); 129bdd1243dSDimitry Andric 130bdd1243dSDimitry Andric Type *ArrayEltTy = cast<ArrayType>(GV->getValueType())->getElementType(); 131bdd1243dSDimitry Andric 132bdd1243dSDimitry Andric SmallVector<Constant *, 16> NewInit; 133bdd1243dSDimitry Andric for (Constant *MaybeRemoved : Init) { 134bdd1243dSDimitry Andric if (!ShouldRemove(MaybeRemoved->stripPointerCasts())) 135bdd1243dSDimitry Andric NewInit.push_back(MaybeRemoved); 136bdd1243dSDimitry Andric } 137bdd1243dSDimitry Andric 138bdd1243dSDimitry Andric if (!NewInit.empty()) { 139bdd1243dSDimitry Andric ArrayType *ATy = ArrayType::get(ArrayEltTy, NewInit.size()); 140bdd1243dSDimitry Andric GlobalVariable *NewGV = 141bdd1243dSDimitry Andric new GlobalVariable(M, ATy, false, GlobalValue::AppendingLinkage, 142bdd1243dSDimitry Andric ConstantArray::get(ATy, NewInit), "", GV, 143bdd1243dSDimitry Andric GV->getThreadLocalMode(), GV->getAddressSpace()); 144bdd1243dSDimitry Andric NewGV->setSection(GV->getSection()); 145bdd1243dSDimitry Andric NewGV->takeName(GV); 146bdd1243dSDimitry Andric } 147bdd1243dSDimitry Andric 148bdd1243dSDimitry Andric GV->eraseFromParent(); 149bdd1243dSDimitry Andric } 150bdd1243dSDimitry Andric 151bdd1243dSDimitry Andric void llvm::removeFromUsedLists(Module &M, 152bdd1243dSDimitry Andric function_ref<bool(Constant *)> ShouldRemove) { 153bdd1243dSDimitry Andric removeFromUsedList(M, "llvm.used", ShouldRemove); 154bdd1243dSDimitry Andric removeFromUsedList(M, "llvm.compiler.used", ShouldRemove); 155bdd1243dSDimitry Andric } 156bdd1243dSDimitry Andric 157bdd1243dSDimitry Andric void llvm::setKCFIType(Module &M, Function &F, StringRef MangledType) { 158bdd1243dSDimitry Andric if (!M.getModuleFlag("kcfi")) 159bdd1243dSDimitry Andric return; 160bdd1243dSDimitry Andric // Matches CodeGenModule::CreateKCFITypeId in Clang. 161bdd1243dSDimitry Andric LLVMContext &Ctx = M.getContext(); 162bdd1243dSDimitry Andric MDBuilder MDB(Ctx); 163bdd1243dSDimitry Andric F.setMetadata( 164bdd1243dSDimitry Andric LLVMContext::MD_kcfi_type, 165bdd1243dSDimitry Andric MDNode::get(Ctx, MDB.createConstant(ConstantInt::get( 166bdd1243dSDimitry Andric Type::getInt32Ty(Ctx), 167bdd1243dSDimitry Andric static_cast<uint32_t>(xxHash64(MangledType)))))); 168bdd1243dSDimitry Andric // If the module was compiled with -fpatchable-function-entry, ensure 169bdd1243dSDimitry Andric // we use the same patchable-function-prefix. 170bdd1243dSDimitry Andric if (auto *MD = mdconst::extract_or_null<ConstantInt>( 171bdd1243dSDimitry Andric M.getModuleFlag("kcfi-offset"))) { 172bdd1243dSDimitry Andric if (unsigned Offset = MD->getZExtValue()) 173bdd1243dSDimitry Andric F.addFnAttr("patchable-function-prefix", std::to_string(Offset)); 174bdd1243dSDimitry Andric } 175bdd1243dSDimitry Andric } 176bdd1243dSDimitry Andric 177bdd1243dSDimitry Andric FunctionCallee llvm::declareSanitizerInitFunction(Module &M, StringRef InitName, 178bdd1243dSDimitry Andric ArrayRef<Type *> InitArgTypes, 179bdd1243dSDimitry Andric bool Weak) { 1800b57cec5SDimitry Andric assert(!InitName.empty() && "Expected init function name"); 181bdd1243dSDimitry Andric auto *VoidTy = Type::getVoidTy(M.getContext()); 182bdd1243dSDimitry Andric auto *FnTy = FunctionType::get(VoidTy, InitArgTypes, false); 183bdd1243dSDimitry Andric auto FnCallee = M.getOrInsertFunction(InitName, FnTy); 184bdd1243dSDimitry Andric auto *Fn = cast<Function>(FnCallee.getCallee()); 185bdd1243dSDimitry Andric if (Weak && Fn->isDeclaration()) 186bdd1243dSDimitry Andric Fn->setLinkage(Function::ExternalWeakLinkage); 187bdd1243dSDimitry Andric return FnCallee; 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1905ffd83dbSDimitry Andric Function *llvm::createSanitizerCtor(Module &M, StringRef CtorName) { 191fe6060f1SDimitry Andric Function *Ctor = Function::createWithDefaultAttr( 1925ffd83dbSDimitry Andric FunctionType::get(Type::getVoidTy(M.getContext()), false), 193bdd1243dSDimitry Andric GlobalValue::InternalLinkage, M.getDataLayout().getProgramAddressSpace(), 194bdd1243dSDimitry Andric CtorName, &M); 195349cc55cSDimitry Andric Ctor->addFnAttr(Attribute::NoUnwind); 196bdd1243dSDimitry Andric setKCFIType(M, *Ctor, "_ZTSFvvE"); // void (*)(void) 1975ffd83dbSDimitry Andric BasicBlock *CtorBB = BasicBlock::Create(M.getContext(), "", Ctor); 1985ffd83dbSDimitry Andric ReturnInst::Create(M.getContext(), CtorBB); 199fe6060f1SDimitry Andric // Ensure Ctor cannot be discarded, even if in a comdat. 200fe6060f1SDimitry Andric appendToUsed(M, {Ctor}); 2015ffd83dbSDimitry Andric return Ctor; 2025ffd83dbSDimitry Andric } 2035ffd83dbSDimitry Andric 2040b57cec5SDimitry Andric std::pair<Function *, FunctionCallee> llvm::createSanitizerCtorAndInitFunctions( 2050b57cec5SDimitry Andric Module &M, StringRef CtorName, StringRef InitName, 2060b57cec5SDimitry Andric ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs, 207bdd1243dSDimitry Andric StringRef VersionCheckName, bool Weak) { 2080b57cec5SDimitry Andric assert(!InitName.empty() && "Expected init function name"); 2090b57cec5SDimitry Andric assert(InitArgs.size() == InitArgTypes.size() && 2100b57cec5SDimitry Andric "Sanitizer's init function expects different number of arguments"); 2110b57cec5SDimitry Andric FunctionCallee InitFunction = 212bdd1243dSDimitry Andric declareSanitizerInitFunction(M, InitName, InitArgTypes, Weak); 2135ffd83dbSDimitry Andric Function *Ctor = createSanitizerCtor(M, CtorName); 214bdd1243dSDimitry Andric IRBuilder<> IRB(M.getContext()); 215bdd1243dSDimitry Andric 216bdd1243dSDimitry Andric BasicBlock *RetBB = &Ctor->getEntryBlock(); 217bdd1243dSDimitry Andric if (Weak) { 218bdd1243dSDimitry Andric RetBB->setName("ret"); 219bdd1243dSDimitry Andric auto *EntryBB = BasicBlock::Create(M.getContext(), "entry", Ctor, RetBB); 220bdd1243dSDimitry Andric auto *CallInitBB = 221bdd1243dSDimitry Andric BasicBlock::Create(M.getContext(), "callfunc", Ctor, RetBB); 222bdd1243dSDimitry Andric auto *InitFn = cast<Function>(InitFunction.getCallee()); 223bdd1243dSDimitry Andric auto *InitFnPtr = 224bdd1243dSDimitry Andric PointerType::get(InitFn->getType(), InitFn->getAddressSpace()); 225bdd1243dSDimitry Andric IRB.SetInsertPoint(EntryBB); 226bdd1243dSDimitry Andric Value *InitNotNull = 227bdd1243dSDimitry Andric IRB.CreateICmpNE(InitFn, ConstantPointerNull::get(InitFnPtr)); 228bdd1243dSDimitry Andric IRB.CreateCondBr(InitNotNull, CallInitBB, RetBB); 229bdd1243dSDimitry Andric IRB.SetInsertPoint(CallInitBB); 230bdd1243dSDimitry Andric } else { 231bdd1243dSDimitry Andric IRB.SetInsertPoint(RetBB->getTerminator()); 232bdd1243dSDimitry Andric } 233bdd1243dSDimitry Andric 2340b57cec5SDimitry Andric IRB.CreateCall(InitFunction, InitArgs); 2350b57cec5SDimitry Andric if (!VersionCheckName.empty()) { 2360b57cec5SDimitry Andric FunctionCallee VersionCheckFunction = M.getOrInsertFunction( 2370b57cec5SDimitry Andric VersionCheckName, FunctionType::get(IRB.getVoidTy(), {}, false), 2380b57cec5SDimitry Andric AttributeList()); 2390b57cec5SDimitry Andric IRB.CreateCall(VersionCheckFunction, {}); 2400b57cec5SDimitry Andric } 241bdd1243dSDimitry Andric 242bdd1243dSDimitry Andric if (Weak) 243bdd1243dSDimitry Andric IRB.CreateBr(RetBB); 244bdd1243dSDimitry Andric 2450b57cec5SDimitry Andric return std::make_pair(Ctor, InitFunction); 2460b57cec5SDimitry Andric } 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric std::pair<Function *, FunctionCallee> 2490b57cec5SDimitry Andric llvm::getOrCreateSanitizerCtorAndInitFunctions( 2500b57cec5SDimitry Andric Module &M, StringRef CtorName, StringRef InitName, 2510b57cec5SDimitry Andric ArrayRef<Type *> InitArgTypes, ArrayRef<Value *> InitArgs, 2520b57cec5SDimitry Andric function_ref<void(Function *, FunctionCallee)> FunctionsCreatedCallback, 253bdd1243dSDimitry Andric StringRef VersionCheckName, bool Weak) { 2540b57cec5SDimitry Andric assert(!CtorName.empty() && "Expected ctor function name"); 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric if (Function *Ctor = M.getFunction(CtorName)) 2570b57cec5SDimitry Andric // FIXME: Sink this logic into the module, similar to the handling of 2580b57cec5SDimitry Andric // globals. This will make moving to a concurrent model much easier. 259349cc55cSDimitry Andric if (Ctor->arg_empty() || 2600b57cec5SDimitry Andric Ctor->getReturnType() == Type::getVoidTy(M.getContext())) 261bdd1243dSDimitry Andric return {Ctor, 262bdd1243dSDimitry Andric declareSanitizerInitFunction(M, InitName, InitArgTypes, Weak)}; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric Function *Ctor; 2650b57cec5SDimitry Andric FunctionCallee InitFunction; 2660b57cec5SDimitry Andric std::tie(Ctor, InitFunction) = llvm::createSanitizerCtorAndInitFunctions( 267bdd1243dSDimitry Andric M, CtorName, InitName, InitArgTypes, InitArgs, VersionCheckName, Weak); 2680b57cec5SDimitry Andric FunctionsCreatedCallback(Ctor, InitFunction); 2690b57cec5SDimitry Andric return std::make_pair(Ctor, InitFunction); 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric void llvm::filterDeadComdatFunctions( 27304eeddc0SDimitry Andric SmallVectorImpl<Function *> &DeadComdatFunctions) { 27404eeddc0SDimitry Andric SmallPtrSet<Function *, 32> MaybeDeadFunctions; 27504eeddc0SDimitry Andric SmallPtrSet<Comdat *, 32> MaybeDeadComdats; 2760b57cec5SDimitry Andric for (Function *F : DeadComdatFunctions) { 27704eeddc0SDimitry Andric MaybeDeadFunctions.insert(F); 27804eeddc0SDimitry Andric if (Comdat *C = F->getComdat()) 27904eeddc0SDimitry Andric MaybeDeadComdats.insert(C); 28004eeddc0SDimitry Andric } 28104eeddc0SDimitry Andric 28204eeddc0SDimitry Andric // Find comdats for which all users are dead now. 28304eeddc0SDimitry Andric SmallPtrSet<Comdat *, 32> DeadComdats; 28404eeddc0SDimitry Andric for (Comdat *C : MaybeDeadComdats) { 28504eeddc0SDimitry Andric auto IsUserDead = [&](GlobalObject *GO) { 28604eeddc0SDimitry Andric auto *F = dyn_cast<Function>(GO); 28704eeddc0SDimitry Andric return F && MaybeDeadFunctions.contains(F); 28804eeddc0SDimitry Andric }; 28904eeddc0SDimitry Andric if (all_of(C->getUsers(), IsUserDead)) 29004eeddc0SDimitry Andric DeadComdats.insert(C); 29104eeddc0SDimitry Andric } 29204eeddc0SDimitry Andric 29304eeddc0SDimitry Andric // Only keep functions which have no comdat or a dead comdat. 29404eeddc0SDimitry Andric erase_if(DeadComdatFunctions, [&](Function *F) { 2950b57cec5SDimitry Andric Comdat *C = F->getComdat(); 29604eeddc0SDimitry Andric return C && !DeadComdats.contains(C); 2970b57cec5SDimitry Andric }); 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric std::string llvm::getUniqueModuleId(Module *M) { 3010b57cec5SDimitry Andric MD5 Md5; 3020b57cec5SDimitry Andric bool ExportsSymbols = false; 3030b57cec5SDimitry Andric auto AddGlobal = [&](GlobalValue &GV) { 3040b57cec5SDimitry Andric if (GV.isDeclaration() || GV.getName().startswith("llvm.") || 3050b57cec5SDimitry Andric !GV.hasExternalLinkage() || GV.hasComdat()) 3060b57cec5SDimitry Andric return; 3070b57cec5SDimitry Andric ExportsSymbols = true; 3080b57cec5SDimitry Andric Md5.update(GV.getName()); 3090b57cec5SDimitry Andric Md5.update(ArrayRef<uint8_t>{0}); 3100b57cec5SDimitry Andric }; 3110b57cec5SDimitry Andric 3120b57cec5SDimitry Andric for (auto &F : *M) 3130b57cec5SDimitry Andric AddGlobal(F); 3140b57cec5SDimitry Andric for (auto &GV : M->globals()) 3150b57cec5SDimitry Andric AddGlobal(GV); 3160b57cec5SDimitry Andric for (auto &GA : M->aliases()) 3170b57cec5SDimitry Andric AddGlobal(GA); 3180b57cec5SDimitry Andric for (auto &IF : M->ifuncs()) 3190b57cec5SDimitry Andric AddGlobal(IF); 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric if (!ExportsSymbols) 3220b57cec5SDimitry Andric return ""; 3230b57cec5SDimitry Andric 3240b57cec5SDimitry Andric MD5::MD5Result R; 3250b57cec5SDimitry Andric Md5.final(R); 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric SmallString<32> Str; 3280b57cec5SDimitry Andric MD5::stringifyResult(R, Str); 329fe6060f1SDimitry Andric return ("." + Str).str(); 3300b57cec5SDimitry Andric } 331480093f4SDimitry Andric 33281ad6265SDimitry Andric void VFABI::setVectorVariantNames(CallInst *CI, 33381ad6265SDimitry Andric ArrayRef<std::string> VariantMappings) { 334480093f4SDimitry Andric if (VariantMappings.empty()) 335480093f4SDimitry Andric return; 336480093f4SDimitry Andric 337480093f4SDimitry Andric SmallString<256> Buffer; 338480093f4SDimitry Andric llvm::raw_svector_ostream Out(Buffer); 339480093f4SDimitry Andric for (const std::string &VariantMapping : VariantMappings) 340480093f4SDimitry Andric Out << VariantMapping << ","; 341480093f4SDimitry Andric // Get rid of the trailing ','. 342480093f4SDimitry Andric assert(!Buffer.str().empty() && "Must have at least one char."); 343480093f4SDimitry Andric Buffer.pop_back(); 344480093f4SDimitry Andric 345480093f4SDimitry Andric Module *M = CI->getModule(); 346480093f4SDimitry Andric #ifndef NDEBUG 347480093f4SDimitry Andric for (const std::string &VariantMapping : VariantMappings) { 3485ffd83dbSDimitry Andric LLVM_DEBUG(dbgs() << "VFABI: adding mapping '" << VariantMapping << "'\n"); 349bdd1243dSDimitry Andric std::optional<VFInfo> VI = VFABI::tryDemangleForVFABI(VariantMapping, *M); 35081ad6265SDimitry Andric assert(VI && "Cannot add an invalid VFABI name."); 351bdd1243dSDimitry Andric assert(M->getNamedValue(VI->VectorName) && 352480093f4SDimitry Andric "Cannot add variant to attribute: " 353480093f4SDimitry Andric "vector function declaration is missing."); 354480093f4SDimitry Andric } 355480093f4SDimitry Andric #endif 356349cc55cSDimitry Andric CI->addFnAttr( 357480093f4SDimitry Andric Attribute::get(M->getContext(), MappingsAttrName, Buffer.str())); 358480093f4SDimitry Andric } 3591fd87a68SDimitry Andric 3601fd87a68SDimitry Andric void llvm::embedBufferInModule(Module &M, MemoryBufferRef Buf, 36181ad6265SDimitry Andric StringRef SectionName, Align Alignment) { 36281ad6265SDimitry Andric // Embed the memory buffer into the module. 3631fd87a68SDimitry Andric Constant *ModuleConstant = ConstantDataArray::get( 364bdd1243dSDimitry Andric M.getContext(), ArrayRef(Buf.getBufferStart(), Buf.getBufferSize())); 3651fd87a68SDimitry Andric GlobalVariable *GV = new GlobalVariable( 3661fd87a68SDimitry Andric M, ModuleConstant->getType(), true, GlobalValue::PrivateLinkage, 3671fd87a68SDimitry Andric ModuleConstant, "llvm.embedded.object"); 3681fd87a68SDimitry Andric GV->setSection(SectionName); 36981ad6265SDimitry Andric GV->setAlignment(Alignment); 3701fd87a68SDimitry Andric 371753f127fSDimitry Andric LLVMContext &Ctx = M.getContext(); 372753f127fSDimitry Andric NamedMDNode *MD = M.getOrInsertNamedMetadata("llvm.embedded.objects"); 373753f127fSDimitry Andric Metadata *MDVals[] = {ConstantAsMetadata::get(GV), 374753f127fSDimitry Andric MDString::get(Ctx, SectionName)}; 375753f127fSDimitry Andric 376753f127fSDimitry Andric MD->addOperand(llvm::MDNode::get(Ctx, MDVals)); 377753f127fSDimitry Andric GV->setMetadata(LLVMContext::MD_exclude, llvm::MDNode::get(Ctx, {})); 378753f127fSDimitry Andric 3791fd87a68SDimitry Andric appendToCompilerUsed(M, GV); 3801fd87a68SDimitry Andric } 381bdd1243dSDimitry Andric 382bdd1243dSDimitry Andric bool llvm::lowerGlobalIFuncUsersAsGlobalCtor( 383bdd1243dSDimitry Andric Module &M, ArrayRef<GlobalIFunc *> FilteredIFuncsToLower) { 384bdd1243dSDimitry Andric SmallVector<GlobalIFunc *, 32> AllIFuncs; 385bdd1243dSDimitry Andric ArrayRef<GlobalIFunc *> IFuncsToLower = FilteredIFuncsToLower; 386bdd1243dSDimitry Andric if (FilteredIFuncsToLower.empty()) { // Default to lowering all ifuncs 387bdd1243dSDimitry Andric for (GlobalIFunc &GI : M.ifuncs()) 388bdd1243dSDimitry Andric AllIFuncs.push_back(&GI); 389bdd1243dSDimitry Andric IFuncsToLower = AllIFuncs; 390bdd1243dSDimitry Andric } 391bdd1243dSDimitry Andric 392bdd1243dSDimitry Andric bool UnhandledUsers = false; 393bdd1243dSDimitry Andric LLVMContext &Ctx = M.getContext(); 394bdd1243dSDimitry Andric const DataLayout &DL = M.getDataLayout(); 395bdd1243dSDimitry Andric 396bdd1243dSDimitry Andric PointerType *TableEntryTy = 397*fe013be4SDimitry Andric PointerType::get(Ctx, DL.getProgramAddressSpace()); 398bdd1243dSDimitry Andric 399bdd1243dSDimitry Andric ArrayType *FuncPtrTableTy = 400bdd1243dSDimitry Andric ArrayType::get(TableEntryTy, IFuncsToLower.size()); 401bdd1243dSDimitry Andric 402bdd1243dSDimitry Andric Align PtrAlign = DL.getABITypeAlign(TableEntryTy); 403bdd1243dSDimitry Andric 404bdd1243dSDimitry Andric // Create a global table of function pointers we'll initialize in a global 405bdd1243dSDimitry Andric // constructor. 406bdd1243dSDimitry Andric auto *FuncPtrTable = new GlobalVariable( 407bdd1243dSDimitry Andric M, FuncPtrTableTy, false, GlobalValue::InternalLinkage, 408bdd1243dSDimitry Andric PoisonValue::get(FuncPtrTableTy), "", nullptr, 409bdd1243dSDimitry Andric GlobalVariable::NotThreadLocal, DL.getDefaultGlobalsAddressSpace()); 410bdd1243dSDimitry Andric FuncPtrTable->setAlignment(PtrAlign); 411bdd1243dSDimitry Andric 412bdd1243dSDimitry Andric // Create a function to initialize the function pointer table. 413bdd1243dSDimitry Andric Function *NewCtor = Function::Create( 414bdd1243dSDimitry Andric FunctionType::get(Type::getVoidTy(Ctx), false), Function::InternalLinkage, 415bdd1243dSDimitry Andric DL.getProgramAddressSpace(), "", &M); 416bdd1243dSDimitry Andric 417bdd1243dSDimitry Andric BasicBlock *BB = BasicBlock::Create(Ctx, "", NewCtor); 418bdd1243dSDimitry Andric IRBuilder<> InitBuilder(BB); 419bdd1243dSDimitry Andric 420bdd1243dSDimitry Andric size_t TableIndex = 0; 421bdd1243dSDimitry Andric for (GlobalIFunc *GI : IFuncsToLower) { 422bdd1243dSDimitry Andric Function *ResolvedFunction = GI->getResolverFunction(); 423bdd1243dSDimitry Andric 424bdd1243dSDimitry Andric // We don't know what to pass to a resolver function taking arguments 425bdd1243dSDimitry Andric // 426bdd1243dSDimitry Andric // FIXME: Is this even valid? clang and gcc don't complain but this 427bdd1243dSDimitry Andric // probably should be invalid IR. We could just pass through undef. 428bdd1243dSDimitry Andric if (!std::empty(ResolvedFunction->getFunctionType()->params())) { 429bdd1243dSDimitry Andric LLVM_DEBUG(dbgs() << "Not lowering ifunc resolver function " 430bdd1243dSDimitry Andric << ResolvedFunction->getName() << " with parameters\n"); 431bdd1243dSDimitry Andric UnhandledUsers = true; 432bdd1243dSDimitry Andric continue; 433bdd1243dSDimitry Andric } 434bdd1243dSDimitry Andric 435bdd1243dSDimitry Andric // Initialize the function pointer table. 436bdd1243dSDimitry Andric CallInst *ResolvedFunc = InitBuilder.CreateCall(ResolvedFunction); 437bdd1243dSDimitry Andric Value *Casted = InitBuilder.CreatePointerCast(ResolvedFunc, TableEntryTy); 438bdd1243dSDimitry Andric Constant *GEP = cast<Constant>(InitBuilder.CreateConstInBoundsGEP2_32( 439bdd1243dSDimitry Andric FuncPtrTableTy, FuncPtrTable, 0, TableIndex++)); 440bdd1243dSDimitry Andric InitBuilder.CreateAlignedStore(Casted, GEP, PtrAlign); 441bdd1243dSDimitry Andric 442bdd1243dSDimitry Andric // Update all users to load a pointer from the global table. 443bdd1243dSDimitry Andric for (User *User : make_early_inc_range(GI->users())) { 444bdd1243dSDimitry Andric Instruction *UserInst = dyn_cast<Instruction>(User); 445bdd1243dSDimitry Andric if (!UserInst) { 446bdd1243dSDimitry Andric // TODO: Should handle constantexpr casts in user instructions. Probably 447bdd1243dSDimitry Andric // can't do much about constant initializers. 448bdd1243dSDimitry Andric UnhandledUsers = true; 449bdd1243dSDimitry Andric continue; 450bdd1243dSDimitry Andric } 451bdd1243dSDimitry Andric 452bdd1243dSDimitry Andric IRBuilder<> UseBuilder(UserInst); 453bdd1243dSDimitry Andric LoadInst *ResolvedTarget = 454bdd1243dSDimitry Andric UseBuilder.CreateAlignedLoad(TableEntryTy, GEP, PtrAlign); 455bdd1243dSDimitry Andric Value *ResolvedCast = 456bdd1243dSDimitry Andric UseBuilder.CreatePointerCast(ResolvedTarget, GI->getType()); 457bdd1243dSDimitry Andric UserInst->replaceUsesOfWith(GI, ResolvedCast); 458bdd1243dSDimitry Andric } 459bdd1243dSDimitry Andric 460bdd1243dSDimitry Andric // If we handled all users, erase the ifunc. 461bdd1243dSDimitry Andric if (GI->use_empty()) 462bdd1243dSDimitry Andric GI->eraseFromParent(); 463bdd1243dSDimitry Andric } 464bdd1243dSDimitry Andric 465bdd1243dSDimitry Andric InitBuilder.CreateRetVoid(); 466bdd1243dSDimitry Andric 467*fe013be4SDimitry Andric PointerType *ConstantDataTy = PointerType::get(Ctx, 0); 468bdd1243dSDimitry Andric 469bdd1243dSDimitry Andric // TODO: Is this the right priority? Probably should be before any other 470bdd1243dSDimitry Andric // constructors? 471bdd1243dSDimitry Andric const int Priority = 10; 472bdd1243dSDimitry Andric appendToGlobalCtors(M, NewCtor, Priority, 473bdd1243dSDimitry Andric ConstantPointerNull::get(ConstantDataTy)); 474bdd1243dSDimitry Andric return UnhandledUsers; 475bdd1243dSDimitry Andric } 476