161ba2e39SJustin Bogner //===-- InstrProfiling.cpp - Frontend instrumentation based profiling -----===// 261ba2e39SJustin Bogner // 361ba2e39SJustin Bogner // The LLVM Compiler Infrastructure 461ba2e39SJustin Bogner // 561ba2e39SJustin Bogner // This file is distributed under the University of Illinois Open Source 661ba2e39SJustin Bogner // License. See LICENSE.TXT for details. 761ba2e39SJustin Bogner // 861ba2e39SJustin Bogner //===----------------------------------------------------------------------===// 961ba2e39SJustin Bogner // 1061ba2e39SJustin Bogner // This pass lowers instrprof_increment intrinsics emitted by a frontend for 1161ba2e39SJustin Bogner // profiling. It also builds the data structures and initialization code needed 1261ba2e39SJustin Bogner // for updating execution counts and emitting the profile at runtime. 1361ba2e39SJustin Bogner // 1461ba2e39SJustin Bogner //===----------------------------------------------------------------------===// 1561ba2e39SJustin Bogner 1661ba2e39SJustin Bogner #include "llvm/Transforms/Instrumentation.h" 1761ba2e39SJustin Bogner 1861ba2e39SJustin Bogner #include "llvm/ADT/Triple.h" 1961ba2e39SJustin Bogner #include "llvm/IR/IRBuilder.h" 2061ba2e39SJustin Bogner #include "llvm/IR/IntrinsicInst.h" 2161ba2e39SJustin Bogner #include "llvm/IR/Module.h" 2261ba2e39SJustin Bogner #include "llvm/Transforms/Utils/ModuleUtils.h" 2361ba2e39SJustin Bogner 2461ba2e39SJustin Bogner using namespace llvm; 2561ba2e39SJustin Bogner 2661ba2e39SJustin Bogner #define DEBUG_TYPE "instrprof" 2761ba2e39SJustin Bogner 2861ba2e39SJustin Bogner namespace { 2961ba2e39SJustin Bogner 3061ba2e39SJustin Bogner class InstrProfiling : public ModulePass { 3161ba2e39SJustin Bogner public: 3261ba2e39SJustin Bogner static char ID; 3361ba2e39SJustin Bogner 3461ba2e39SJustin Bogner InstrProfiling() : ModulePass(ID) {} 3561ba2e39SJustin Bogner 3661ba2e39SJustin Bogner InstrProfiling(const InstrProfOptions &Options) 3761ba2e39SJustin Bogner : ModulePass(ID), Options(Options) {} 3861ba2e39SJustin Bogner 3961ba2e39SJustin Bogner const char *getPassName() const override { 4061ba2e39SJustin Bogner return "Frontend instrumentation-based coverage lowering"; 4161ba2e39SJustin Bogner } 4261ba2e39SJustin Bogner 4361ba2e39SJustin Bogner bool runOnModule(Module &M) override; 4461ba2e39SJustin Bogner 4561ba2e39SJustin Bogner void getAnalysisUsage(AnalysisUsage &AU) const override { 4661ba2e39SJustin Bogner AU.setPreservesCFG(); 4761ba2e39SJustin Bogner } 4861ba2e39SJustin Bogner 4961ba2e39SJustin Bogner private: 5061ba2e39SJustin Bogner InstrProfOptions Options; 5161ba2e39SJustin Bogner Module *M; 5261ba2e39SJustin Bogner DenseMap<GlobalVariable *, GlobalVariable *> RegionCounters; 5361ba2e39SJustin Bogner std::vector<Value *> UsedVars; 5461ba2e39SJustin Bogner 5561ba2e39SJustin Bogner bool isMachO() const { 5661ba2e39SJustin Bogner return Triple(M->getTargetTriple()).isOSBinFormatMachO(); 5761ba2e39SJustin Bogner } 5861ba2e39SJustin Bogner 5961ba2e39SJustin Bogner /// Get the section name for the counter variables. 6061ba2e39SJustin Bogner StringRef getCountersSection() const { 6161ba2e39SJustin Bogner return isMachO() ? "__DATA,__llvm_prf_cnts" : "__llvm_prf_cnts"; 6261ba2e39SJustin Bogner } 6361ba2e39SJustin Bogner 6461ba2e39SJustin Bogner /// Get the section name for the name variables. 6561ba2e39SJustin Bogner StringRef getNameSection() const { 6661ba2e39SJustin Bogner return isMachO() ? "__DATA,__llvm_prf_names" : "__llvm_prf_names"; 6761ba2e39SJustin Bogner } 6861ba2e39SJustin Bogner 6961ba2e39SJustin Bogner /// Get the section name for the profile data variables. 7061ba2e39SJustin Bogner StringRef getDataSection() const { 7161ba2e39SJustin Bogner return isMachO() ? "__DATA,__llvm_prf_data" : "__llvm_prf_data"; 7261ba2e39SJustin Bogner } 7361ba2e39SJustin Bogner 74d24e1857SJustin Bogner /// Get the section name for the coverage mapping data. 75d24e1857SJustin Bogner StringRef getCoverageSection() const { 76d24e1857SJustin Bogner return isMachO() ? "__DATA,__llvm_covmap" : "__llvm_covmap"; 77d24e1857SJustin Bogner } 78d24e1857SJustin Bogner 7961ba2e39SJustin Bogner /// Replace instrprof_increment with an increment of the appropriate value. 8061ba2e39SJustin Bogner void lowerIncrement(InstrProfIncrementInst *Inc); 8161ba2e39SJustin Bogner 82d24e1857SJustin Bogner /// Set up the section and uses for coverage data and its references. 83d24e1857SJustin Bogner void lowerCoverageData(GlobalVariable *CoverageData); 84d24e1857SJustin Bogner 8561ba2e39SJustin Bogner /// Get the region counters for an increment, creating them if necessary. 8661ba2e39SJustin Bogner /// 8761ba2e39SJustin Bogner /// If the counter array doesn't yet exist, the profile data variables 8861ba2e39SJustin Bogner /// referring to them will also be created. 8961ba2e39SJustin Bogner GlobalVariable *getOrCreateRegionCounters(InstrProfIncrementInst *Inc); 9061ba2e39SJustin Bogner 9161ba2e39SJustin Bogner /// Emit runtime registration functions for each profile data variable. 9261ba2e39SJustin Bogner void emitRegistration(); 9361ba2e39SJustin Bogner 9461ba2e39SJustin Bogner /// Emit the necessary plumbing to pull in the runtime initialization. 9561ba2e39SJustin Bogner void emitRuntimeHook(); 9661ba2e39SJustin Bogner 9761ba2e39SJustin Bogner /// Add uses of our data variables and runtime hook. 9861ba2e39SJustin Bogner void emitUses(); 9961ba2e39SJustin Bogner 100ba1900ceSJustin Bogner /// Create a static initializer for our data, on platforms that need it, 101ba1900ceSJustin Bogner /// and for any profile output file that was specified. 10261ba2e39SJustin Bogner void emitInitialization(); 10361ba2e39SJustin Bogner }; 10461ba2e39SJustin Bogner 10561ba2e39SJustin Bogner } // anonymous namespace 10661ba2e39SJustin Bogner 10761ba2e39SJustin Bogner char InstrProfiling::ID = 0; 10861ba2e39SJustin Bogner INITIALIZE_PASS(InstrProfiling, "instrprof", 10961ba2e39SJustin Bogner "Frontend instrumentation-based coverage lowering.", false, 11061ba2e39SJustin Bogner false) 11161ba2e39SJustin Bogner 11261ba2e39SJustin Bogner ModulePass *llvm::createInstrProfilingPass(const InstrProfOptions &Options) { 11361ba2e39SJustin Bogner return new InstrProfiling(Options); 11461ba2e39SJustin Bogner } 11561ba2e39SJustin Bogner 11661ba2e39SJustin Bogner bool InstrProfiling::runOnModule(Module &M) { 11761ba2e39SJustin Bogner bool MadeChange = false; 11861ba2e39SJustin Bogner 11961ba2e39SJustin Bogner this->M = &M; 12061ba2e39SJustin Bogner RegionCounters.clear(); 12161ba2e39SJustin Bogner UsedVars.clear(); 12261ba2e39SJustin Bogner 12361ba2e39SJustin Bogner for (Function &F : M) 12461ba2e39SJustin Bogner for (BasicBlock &BB : F) 12561ba2e39SJustin Bogner for (auto I = BB.begin(), E = BB.end(); I != E;) 12661ba2e39SJustin Bogner if (auto *Inc = dyn_cast<InstrProfIncrementInst>(I++)) { 12761ba2e39SJustin Bogner lowerIncrement(Inc); 12861ba2e39SJustin Bogner MadeChange = true; 12961ba2e39SJustin Bogner } 130d24e1857SJustin Bogner if (GlobalVariable *Coverage = M.getNamedGlobal("__llvm_coverage_mapping")) { 131d24e1857SJustin Bogner lowerCoverageData(Coverage); 132d24e1857SJustin Bogner MadeChange = true; 133d24e1857SJustin Bogner } 13461ba2e39SJustin Bogner if (!MadeChange) 13561ba2e39SJustin Bogner return false; 13661ba2e39SJustin Bogner 13761ba2e39SJustin Bogner emitRegistration(); 13861ba2e39SJustin Bogner emitRuntimeHook(); 13961ba2e39SJustin Bogner emitUses(); 14061ba2e39SJustin Bogner emitInitialization(); 14161ba2e39SJustin Bogner return true; 14261ba2e39SJustin Bogner } 14361ba2e39SJustin Bogner 14461ba2e39SJustin Bogner void InstrProfiling::lowerIncrement(InstrProfIncrementInst *Inc) { 14561ba2e39SJustin Bogner GlobalVariable *Counters = getOrCreateRegionCounters(Inc); 14661ba2e39SJustin Bogner 147*e82c286fSDuncan P. N. Exon Smith IRBuilder<> Builder(Inc); 14861ba2e39SJustin Bogner uint64_t Index = Inc->getIndex()->getZExtValue(); 149b3029d26SDiego Novillo Value *Addr = Builder.CreateConstInBoundsGEP2_64(Counters, 0, Index); 150b3029d26SDiego Novillo Value *Count = Builder.CreateLoad(Addr, "pgocount"); 15161ba2e39SJustin Bogner Count = Builder.CreateAdd(Count, Builder.getInt64(1)); 15261ba2e39SJustin Bogner Inc->replaceAllUsesWith(Builder.CreateStore(Count, Addr)); 15361ba2e39SJustin Bogner Inc->eraseFromParent(); 15461ba2e39SJustin Bogner } 15561ba2e39SJustin Bogner 156d24e1857SJustin Bogner void InstrProfiling::lowerCoverageData(GlobalVariable *CoverageData) { 157d24e1857SJustin Bogner CoverageData->setSection(getCoverageSection()); 158d24e1857SJustin Bogner CoverageData->setAlignment(8); 159d24e1857SJustin Bogner 160d24e1857SJustin Bogner Constant *Init = CoverageData->getInitializer(); 161d24e1857SJustin Bogner // We're expecting { i32, i32, i32, i32, [n x { i8*, i32, i32 }], [m x i8] } 162d24e1857SJustin Bogner // for some C. If not, the frontend's given us something broken. 163d24e1857SJustin Bogner assert(Init->getNumOperands() == 6 && "bad number of fields in coverage map"); 164d24e1857SJustin Bogner assert(isa<ConstantArray>(Init->getAggregateElement(4)) && 165d24e1857SJustin Bogner "invalid function list in coverage map"); 166d24e1857SJustin Bogner ConstantArray *Records = cast<ConstantArray>(Init->getAggregateElement(4)); 167d24e1857SJustin Bogner for (unsigned I = 0, E = Records->getNumOperands(); I < E; ++I) { 168d24e1857SJustin Bogner Constant *Record = Records->getOperand(I); 169d24e1857SJustin Bogner Value *V = const_cast<Value *>(Record->getOperand(0))->stripPointerCasts(); 170d24e1857SJustin Bogner 171d24e1857SJustin Bogner assert(isa<GlobalVariable>(V) && "Missing reference to function name"); 172d24e1857SJustin Bogner GlobalVariable *Name = cast<GlobalVariable>(V); 173d24e1857SJustin Bogner 174d24e1857SJustin Bogner // If we have region counters for this name, we've already handled it. 175d24e1857SJustin Bogner auto It = RegionCounters.find(Name); 176d24e1857SJustin Bogner if (It != RegionCounters.end()) 177d24e1857SJustin Bogner continue; 178d24e1857SJustin Bogner 179d24e1857SJustin Bogner // Move the name variable to the right section. 180d24e1857SJustin Bogner Name->setSection(getNameSection()); 181d24e1857SJustin Bogner Name->setAlignment(1); 182d24e1857SJustin Bogner } 183d24e1857SJustin Bogner } 184d24e1857SJustin Bogner 18561ba2e39SJustin Bogner /// Get the name of a profiling variable for a particular function. 18661ba2e39SJustin Bogner static std::string getVarName(InstrProfIncrementInst *Inc, StringRef VarName) { 18761ba2e39SJustin Bogner auto *Arr = cast<ConstantDataArray>(Inc->getName()->getInitializer()); 18861ba2e39SJustin Bogner StringRef Name = Arr->isCString() ? Arr->getAsCString() : Arr->getAsString(); 18961ba2e39SJustin Bogner return ("__llvm_profile_" + VarName + "_" + Name).str(); 19061ba2e39SJustin Bogner } 19161ba2e39SJustin Bogner 19261ba2e39SJustin Bogner GlobalVariable * 19361ba2e39SJustin Bogner InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) { 19461ba2e39SJustin Bogner GlobalVariable *Name = Inc->getName(); 19561ba2e39SJustin Bogner auto It = RegionCounters.find(Name); 19661ba2e39SJustin Bogner if (It != RegionCounters.end()) 19761ba2e39SJustin Bogner return It->second; 19861ba2e39SJustin Bogner 1993cc9204aSWei Mi // Move the name variable to the right section. Place them in a COMDAT group 2003cc9204aSWei Mi // if the associated function is a COMDAT. This will make sure that 2013cc9204aSWei Mi // only one copy of counters of the COMDAT function will be emitted after 2023cc9204aSWei Mi // linking. 203df4837baSDiego Novillo Function *Fn = Inc->getParent()->getParent(); 2043cc9204aSWei Mi Comdat *ProfileVarsComdat = nullptr; 2053cc9204aSWei Mi if (Fn->hasComdat()) 2063cc9204aSWei Mi ProfileVarsComdat = M->getOrInsertComdat(StringRef(getVarName(Inc, "vars"))); 20761ba2e39SJustin Bogner Name->setSection(getNameSection()); 20861ba2e39SJustin Bogner Name->setAlignment(1); 2093cc9204aSWei Mi Name->setComdat(ProfileVarsComdat); 21061ba2e39SJustin Bogner 21161ba2e39SJustin Bogner uint64_t NumCounters = Inc->getNumCounters()->getZExtValue(); 21261ba2e39SJustin Bogner LLVMContext &Ctx = M->getContext(); 21361ba2e39SJustin Bogner ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters); 21461ba2e39SJustin Bogner 21561ba2e39SJustin Bogner // Create the counters variable. 21661ba2e39SJustin Bogner auto *Counters = new GlobalVariable(*M, CounterTy, false, Name->getLinkage(), 21761ba2e39SJustin Bogner Constant::getNullValue(CounterTy), 21861ba2e39SJustin Bogner getVarName(Inc, "counters")); 21961ba2e39SJustin Bogner Counters->setVisibility(Name->getVisibility()); 22061ba2e39SJustin Bogner Counters->setSection(getCountersSection()); 22161ba2e39SJustin Bogner Counters->setAlignment(8); 2223cc9204aSWei Mi Counters->setComdat(ProfileVarsComdat); 22361ba2e39SJustin Bogner 22461ba2e39SJustin Bogner RegionCounters[Inc->getName()] = Counters; 22561ba2e39SJustin Bogner 22661ba2e39SJustin Bogner // Create data variable. 22761ba2e39SJustin Bogner auto *NameArrayTy = Name->getType()->getPointerElementType(); 22861ba2e39SJustin Bogner auto *Int32Ty = Type::getInt32Ty(Ctx); 22961ba2e39SJustin Bogner auto *Int64Ty = Type::getInt64Ty(Ctx); 23061ba2e39SJustin Bogner auto *Int8PtrTy = Type::getInt8PtrTy(Ctx); 23161ba2e39SJustin Bogner auto *Int64PtrTy = Type::getInt64PtrTy(Ctx); 23261ba2e39SJustin Bogner 23361ba2e39SJustin Bogner Type *DataTypes[] = {Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy}; 23461ba2e39SJustin Bogner auto *DataTy = StructType::get(Ctx, makeArrayRef(DataTypes)); 23561ba2e39SJustin Bogner Constant *DataVals[] = { 23661ba2e39SJustin Bogner ConstantInt::get(Int32Ty, NameArrayTy->getArrayNumElements()), 23761ba2e39SJustin Bogner ConstantInt::get(Int32Ty, NumCounters), 23861ba2e39SJustin Bogner ConstantInt::get(Int64Ty, Inc->getHash()->getZExtValue()), 23961ba2e39SJustin Bogner ConstantExpr::getBitCast(Name, Int8PtrTy), 24061ba2e39SJustin Bogner ConstantExpr::getBitCast(Counters, Int64PtrTy)}; 24161ba2e39SJustin Bogner auto *Data = new GlobalVariable(*M, DataTy, true, Name->getLinkage(), 24261ba2e39SJustin Bogner ConstantStruct::get(DataTy, DataVals), 24361ba2e39SJustin Bogner getVarName(Inc, "data")); 24461ba2e39SJustin Bogner Data->setVisibility(Name->getVisibility()); 24561ba2e39SJustin Bogner Data->setSection(getDataSection()); 24661ba2e39SJustin Bogner Data->setAlignment(8); 2473cc9204aSWei Mi Data->setComdat(ProfileVarsComdat); 24861ba2e39SJustin Bogner 24961ba2e39SJustin Bogner // Mark the data variable as used so that it isn't stripped out. 25061ba2e39SJustin Bogner UsedVars.push_back(Data); 25161ba2e39SJustin Bogner 25261ba2e39SJustin Bogner return Counters; 25361ba2e39SJustin Bogner } 25461ba2e39SJustin Bogner 25561ba2e39SJustin Bogner void InstrProfiling::emitRegistration() { 25661ba2e39SJustin Bogner // Don't do this for Darwin. compiler-rt uses linker magic. 25761ba2e39SJustin Bogner if (Triple(M->getTargetTriple()).isOSDarwin()) 25861ba2e39SJustin Bogner return; 25961ba2e39SJustin Bogner 26061ba2e39SJustin Bogner // Construct the function. 26161ba2e39SJustin Bogner auto *VoidTy = Type::getVoidTy(M->getContext()); 26261ba2e39SJustin Bogner auto *VoidPtrTy = Type::getInt8PtrTy(M->getContext()); 26361ba2e39SJustin Bogner auto *RegisterFTy = FunctionType::get(VoidTy, false); 26461ba2e39SJustin Bogner auto *RegisterF = Function::Create(RegisterFTy, GlobalValue::InternalLinkage, 26561ba2e39SJustin Bogner "__llvm_profile_register_functions", M); 26661ba2e39SJustin Bogner RegisterF->setUnnamedAddr(true); 26761ba2e39SJustin Bogner if (Options.NoRedZone) 26861ba2e39SJustin Bogner RegisterF->addFnAttr(Attribute::NoRedZone); 26961ba2e39SJustin Bogner 270b3029d26SDiego Novillo auto *RuntimeRegisterTy = FunctionType::get(VoidTy, VoidPtrTy, false); 27161ba2e39SJustin Bogner auto *RuntimeRegisterF = 27261ba2e39SJustin Bogner Function::Create(RuntimeRegisterTy, GlobalVariable::ExternalLinkage, 27361ba2e39SJustin Bogner "__llvm_profile_register_function", M); 27461ba2e39SJustin Bogner 27561ba2e39SJustin Bogner IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", RegisterF)); 27661ba2e39SJustin Bogner for (Value *Data : UsedVars) 27761ba2e39SJustin Bogner IRB.CreateCall(RuntimeRegisterF, IRB.CreateBitCast(Data, VoidPtrTy)); 27861ba2e39SJustin Bogner IRB.CreateRetVoid(); 27961ba2e39SJustin Bogner } 28061ba2e39SJustin Bogner 28161ba2e39SJustin Bogner void InstrProfiling::emitRuntimeHook() { 28261ba2e39SJustin Bogner const char *const RuntimeVarName = "__llvm_profile_runtime"; 28361ba2e39SJustin Bogner const char *const RuntimeUserName = "__llvm_profile_runtime_user"; 28461ba2e39SJustin Bogner 28561ba2e39SJustin Bogner // If the module's provided its own runtime, we don't need to do anything. 28661ba2e39SJustin Bogner if (M->getGlobalVariable(RuntimeVarName)) 28761ba2e39SJustin Bogner return; 28861ba2e39SJustin Bogner 28961ba2e39SJustin Bogner // Declare an external variable that will pull in the runtime initialization. 29061ba2e39SJustin Bogner auto *Int32Ty = Type::getInt32Ty(M->getContext()); 29161ba2e39SJustin Bogner auto *Var = 29261ba2e39SJustin Bogner new GlobalVariable(*M, Int32Ty, false, GlobalValue::ExternalLinkage, 29361ba2e39SJustin Bogner nullptr, RuntimeVarName); 29461ba2e39SJustin Bogner 29561ba2e39SJustin Bogner // Make a function that uses it. 29661ba2e39SJustin Bogner auto *User = 29761ba2e39SJustin Bogner Function::Create(FunctionType::get(Int32Ty, false), 29861ba2e39SJustin Bogner GlobalValue::LinkOnceODRLinkage, RuntimeUserName, M); 29961ba2e39SJustin Bogner User->addFnAttr(Attribute::NoInline); 30061ba2e39SJustin Bogner if (Options.NoRedZone) 30161ba2e39SJustin Bogner User->addFnAttr(Attribute::NoRedZone); 3022e427d4dSJustin Bogner User->setVisibility(GlobalValue::HiddenVisibility); 30361ba2e39SJustin Bogner 30461ba2e39SJustin Bogner IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", User)); 30561ba2e39SJustin Bogner auto *Load = IRB.CreateLoad(Var); 30661ba2e39SJustin Bogner IRB.CreateRet(Load); 30761ba2e39SJustin Bogner 30861ba2e39SJustin Bogner // Mark the user variable as used so that it isn't stripped out. 30961ba2e39SJustin Bogner UsedVars.push_back(User); 31061ba2e39SJustin Bogner } 31161ba2e39SJustin Bogner 31261ba2e39SJustin Bogner void InstrProfiling::emitUses() { 31361ba2e39SJustin Bogner if (UsedVars.empty()) 31461ba2e39SJustin Bogner return; 31561ba2e39SJustin Bogner 31661ba2e39SJustin Bogner GlobalVariable *LLVMUsed = M->getGlobalVariable("llvm.used"); 31761ba2e39SJustin Bogner std::vector<Constant *> MergedVars; 31861ba2e39SJustin Bogner if (LLVMUsed) { 31961ba2e39SJustin Bogner // Collect the existing members of llvm.used. 32061ba2e39SJustin Bogner ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer()); 32161ba2e39SJustin Bogner for (unsigned I = 0, E = Inits->getNumOperands(); I != E; ++I) 32261ba2e39SJustin Bogner MergedVars.push_back(Inits->getOperand(I)); 32361ba2e39SJustin Bogner LLVMUsed->eraseFromParent(); 32461ba2e39SJustin Bogner } 32561ba2e39SJustin Bogner 32661ba2e39SJustin Bogner Type *i8PTy = Type::getInt8PtrTy(M->getContext()); 32761ba2e39SJustin Bogner // Add uses for our data. 32861ba2e39SJustin Bogner for (auto *Value : UsedVars) 32961ba2e39SJustin Bogner MergedVars.push_back( 330b3029d26SDiego Novillo ConstantExpr::getBitCast(cast<Constant>(Value), i8PTy)); 33161ba2e39SJustin Bogner 33261ba2e39SJustin Bogner // Recreate llvm.used. 33361ba2e39SJustin Bogner ArrayType *ATy = ArrayType::get(i8PTy, MergedVars.size()); 334b3029d26SDiego Novillo LLVMUsed = 335b3029d26SDiego Novillo new GlobalVariable(*M, ATy, false, GlobalValue::AppendingLinkage, 336b3029d26SDiego Novillo ConstantArray::get(ATy, MergedVars), "llvm.used"); 33761ba2e39SJustin Bogner 33861ba2e39SJustin Bogner LLVMUsed->setSection("llvm.metadata"); 33961ba2e39SJustin Bogner } 34061ba2e39SJustin Bogner 34161ba2e39SJustin Bogner void InstrProfiling::emitInitialization() { 342ba1900ceSJustin Bogner std::string InstrProfileOutput = Options.InstrProfileOutput; 343ba1900ceSJustin Bogner 34461ba2e39SJustin Bogner Constant *RegisterF = M->getFunction("__llvm_profile_register_functions"); 345ba1900ceSJustin Bogner if (!RegisterF && InstrProfileOutput.empty()) 34661ba2e39SJustin Bogner return; 34761ba2e39SJustin Bogner 34861ba2e39SJustin Bogner // Create the initialization function. 34961ba2e39SJustin Bogner auto *VoidTy = Type::getVoidTy(M->getContext()); 35061ba2e39SJustin Bogner auto *F = 35161ba2e39SJustin Bogner Function::Create(FunctionType::get(VoidTy, false), 35261ba2e39SJustin Bogner GlobalValue::InternalLinkage, "__llvm_profile_init", M); 35361ba2e39SJustin Bogner F->setUnnamedAddr(true); 35461ba2e39SJustin Bogner F->addFnAttr(Attribute::NoInline); 35561ba2e39SJustin Bogner if (Options.NoRedZone) 35661ba2e39SJustin Bogner F->addFnAttr(Attribute::NoRedZone); 35761ba2e39SJustin Bogner 35861ba2e39SJustin Bogner // Add the basic block and the necessary calls. 35961ba2e39SJustin Bogner IRBuilder<> IRB(BasicBlock::Create(M->getContext(), "", F)); 360ba1900ceSJustin Bogner if (RegisterF) 361ff6409d0SDavid Blaikie IRB.CreateCall(RegisterF, {}); 362ba1900ceSJustin Bogner if (!InstrProfileOutput.empty()) { 363ba1900ceSJustin Bogner auto *Int8PtrTy = Type::getInt8PtrTy(M->getContext()); 364ba1900ceSJustin Bogner auto *SetNameTy = FunctionType::get(VoidTy, Int8PtrTy, false); 365ba1900ceSJustin Bogner auto *SetNameF = 366ba1900ceSJustin Bogner Function::Create(SetNameTy, GlobalValue::ExternalLinkage, 36703038a56SJustin Bogner "__llvm_profile_override_default_filename", M); 368ba1900ceSJustin Bogner 369b0257c84SDiego Novillo // Create variable for profile name. 370ba1900ceSJustin Bogner Constant *ProfileNameConst = 371ba1900ceSJustin Bogner ConstantDataArray::getString(M->getContext(), InstrProfileOutput, true); 372ba1900ceSJustin Bogner GlobalVariable *ProfileName = 373ba1900ceSJustin Bogner new GlobalVariable(*M, ProfileNameConst->getType(), true, 374ba1900ceSJustin Bogner GlobalValue::PrivateLinkage, ProfileNameConst); 375ba1900ceSJustin Bogner 376ba1900ceSJustin Bogner IRB.CreateCall(SetNameF, IRB.CreatePointerCast(ProfileName, Int8PtrTy)); 377ba1900ceSJustin Bogner } 37861ba2e39SJustin Bogner IRB.CreateRetVoid(); 37961ba2e39SJustin Bogner 38061ba2e39SJustin Bogner appendToGlobalCtors(*M, F, 0); 38161ba2e39SJustin Bogner } 382