static void computeVariableSummary(ModuleSummaryIndex &Index, const GlobalVariable &V, DenseSet<GlobalValue::GUID> &CantBePromoted) { SetVector<ValueInfo> RefEdges; SmallPtrSet<const User *, 8> Visited; findRefEdges(&V, RefEdges, Visited); bool NonRenamableLocal = isNonRenamableLocal(V); GlobalValueSummary::GVFlags Flags(V.getLinkage(), NonRenamableLocal, /* LiveRoot = */ false); auto GVarSummary = llvm::make_unique<GlobalVarSummary>(Flags, RefEdges.takeVector()); if (NonRenamableLocal) CantBePromoted.insert(V.getGUID()); Index.addGlobalValueSummary(V.getName(), std::move(GVarSummary)); }
GlobalVariable * InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) { GlobalVariable *NamePtr = Inc->getName(); auto It = ProfileDataMap.find(NamePtr); PerFunctionProfileData PD; if (It != ProfileDataMap.end()) { if (It->second.RegionCounters) return It->second.RegionCounters; PD = It->second; } // Move the name variable to the right section. Place them in a COMDAT group // if the associated function is a COMDAT. This will make sure that // only one copy of counters of the COMDAT function will be emitted after // linking. Function *Fn = Inc->getParent()->getParent(); Comdat *ProfileVarsComdat = nullptr; ProfileVarsComdat = getOrCreateProfileComdat(*M, *Fn, Inc); uint64_t NumCounters = Inc->getNumCounters()->getZExtValue(); LLVMContext &Ctx = M->getContext(); ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters); // Create the counters variable. auto *CounterPtr = new GlobalVariable(*M, CounterTy, false, NamePtr->getLinkage(), Constant::getNullValue(CounterTy), getVarName(Inc, getInstrProfCountersVarPrefix())); CounterPtr->setVisibility(NamePtr->getVisibility()); CounterPtr->setSection( getInstrProfSectionName(IPSK_cnts, TT.getObjectFormat())); CounterPtr->setAlignment(8); CounterPtr->setComdat(ProfileVarsComdat); auto *Int8PtrTy = Type::getInt8PtrTy(Ctx); // Allocate statically the array of pointers to value profile nodes for // the current function. Constant *ValuesPtrExpr = ConstantPointerNull::get(Int8PtrTy); if (ValueProfileStaticAlloc && !needsRuntimeRegistrationOfSectionRange(*M)) { uint64_t NS = 0; for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) NS += PD.NumValueSites[Kind]; if (NS) { ArrayType *ValuesTy = ArrayType::get(Type::getInt64Ty(Ctx), NS); auto *ValuesVar = new GlobalVariable(*M, ValuesTy, false, NamePtr->getLinkage(), Constant::getNullValue(ValuesTy), getVarName(Inc, getInstrProfValuesVarPrefix())); ValuesVar->setVisibility(NamePtr->getVisibility()); ValuesVar->setSection( getInstrProfSectionName(IPSK_vals, TT.getObjectFormat())); ValuesVar->setAlignment(8); ValuesVar->setComdat(ProfileVarsComdat); ValuesPtrExpr = ConstantExpr::getBitCast(ValuesVar, Type::getInt8PtrTy(Ctx)); } } // Create data variable. auto *Int16Ty = Type::getInt16Ty(Ctx); auto *Int16ArrayTy = ArrayType::get(Int16Ty, IPVK_Last + 1); Type *DataTypes[] = { #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) LLVMType, #include "llvm/ProfileData/InstrProfData.inc" }; auto *DataTy = StructType::get(Ctx, makeArrayRef(DataTypes)); Constant *FunctionAddr = shouldRecordFunctionAddr(Fn) ? ConstantExpr::getBitCast(Fn, Int8PtrTy) : ConstantPointerNull::get(Int8PtrTy); Constant *Int16ArrayVals[IPVK_Last + 1]; for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) Int16ArrayVals[Kind] = ConstantInt::get(Int16Ty, PD.NumValueSites[Kind]); Constant *DataVals[] = { #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Init, #include "llvm/ProfileData/InstrProfData.inc" }; auto *Data = new GlobalVariable(*M, DataTy, false, NamePtr->getLinkage(), ConstantStruct::get(DataTy, DataVals), getVarName(Inc, getInstrProfDataVarPrefix())); Data->setVisibility(NamePtr->getVisibility()); Data->setSection(getInstrProfSectionName(IPSK_data, TT.getObjectFormat())); Data->setAlignment(INSTR_PROF_DATA_ALIGNMENT); Data->setComdat(ProfileVarsComdat); PD.RegionCounters = CounterPtr; PD.DataVar = Data; ProfileDataMap[NamePtr] = PD; // Mark the data variable as used so that it isn't stripped out. UsedVars.push_back(Data); // Now that the linkage set by the FE has been passed to the data and counter // variables, reset Name variable's linkage and visibility to private so that // it can be removed later by the compiler. NamePtr->setLinkage(GlobalValue::PrivateLinkage); // Collect the referenced names to be used by emitNameData. ReferencedNames.push_back(NamePtr); return CounterPtr; }
GlobalVariable * InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) { GlobalVariable *Name = Inc->getName(); auto It = RegionCounters.find(Name); if (It != RegionCounters.end()) return It->second; // Move the name variable to the right section. Place them in a COMDAT group // if the associated function is a COMDAT. This will make sure that // only one copy of counters of the COMDAT function will be emitted after // linking. Function *Fn = Inc->getParent()->getParent(); Comdat *ProfileVarsComdat = nullptr; if (Fn->hasComdat()) ProfileVarsComdat = M->getOrInsertComdat(StringRef(getVarName(Inc, "vars"))); Name->setSection(getNameSection()); Name->setAlignment(1); Name->setComdat(ProfileVarsComdat); uint64_t NumCounters = Inc->getNumCounters()->getZExtValue(); LLVMContext &Ctx = M->getContext(); ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters); // Create the counters variable. auto *Counters = new GlobalVariable(*M, CounterTy, false, Name->getLinkage(), Constant::getNullValue(CounterTy), getVarName(Inc, "counters")); Counters->setVisibility(Name->getVisibility()); Counters->setSection(getCountersSection()); Counters->setAlignment(8); Counters->setComdat(ProfileVarsComdat); RegionCounters[Inc->getName()] = Counters; // Create data variable. auto *NameArrayTy = Name->getType()->getPointerElementType(); auto *Int32Ty = Type::getInt32Ty(Ctx); auto *Int64Ty = Type::getInt64Ty(Ctx); auto *Int8PtrTy = Type::getInt8PtrTy(Ctx); auto *Int64PtrTy = Type::getInt64PtrTy(Ctx); Type *DataTypes[] = {Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy}; auto *DataTy = StructType::get(Ctx, makeArrayRef(DataTypes)); Constant *DataVals[] = { ConstantInt::get(Int32Ty, NameArrayTy->getArrayNumElements()), ConstantInt::get(Int32Ty, NumCounters), ConstantInt::get(Int64Ty, Inc->getHash()->getZExtValue()), ConstantExpr::getBitCast(Name, Int8PtrTy), ConstantExpr::getBitCast(Counters, Int64PtrTy)}; auto *Data = new GlobalVariable(*M, DataTy, true, Name->getLinkage(), ConstantStruct::get(DataTy, DataVals), getVarName(Inc, "data")); Data->setVisibility(Name->getVisibility()); Data->setSection(getDataSection()); Data->setAlignment(8); Data->setComdat(ProfileVarsComdat); // Mark the data variable as used so that it isn't stripped out. UsedVars.push_back(Data); return Counters; }
bool GenericToNVVM::runOnModule(Module &M) { // Create a clone of each global variable that has the default address space. // The clone is created with the global address space specifier, and the pair // of original global variable and its clone is placed in the GVMap for later // use. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E;) { GlobalVariable *GV = &*I++; if (GV->getType()->getAddressSpace() == llvm::ADDRESS_SPACE_GENERIC && !llvm::isTexture(*GV) && !llvm::isSurface(*GV) && !llvm::isSampler(*GV) && !GV->getName().startswith("llvm.")) { GlobalVariable *NewGV = new GlobalVariable( M, GV->getValueType(), GV->isConstant(), GV->getLinkage(), GV->hasInitializer() ? GV->getInitializer() : nullptr, "", GV, GV->getThreadLocalMode(), llvm::ADDRESS_SPACE_GLOBAL); NewGV->copyAttributesFrom(GV); GVMap[GV] = NewGV; } } // Return immediately, if every global variable has a specific address space // specifier. if (GVMap.empty()) { return false; } // Walk through the instructions in function defitinions, and replace any use // of original global variables in GVMap with a use of the corresponding // copies in GVMap. If necessary, promote constants to instructions. for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { if (I->isDeclaration()) { continue; } IRBuilder<> Builder(I->getEntryBlock().getFirstNonPHIOrDbg()); for (Function::iterator BBI = I->begin(), BBE = I->end(); BBI != BBE; ++BBI) { for (BasicBlock::iterator II = BBI->begin(), IE = BBI->end(); II != IE; ++II) { for (unsigned i = 0, e = II->getNumOperands(); i < e; ++i) { Value *Operand = II->getOperand(i); if (isa<Constant>(Operand)) { II->setOperand( i, remapConstant(&M, &*I, cast<Constant>(Operand), Builder)); } } } } ConstantToValueMap.clear(); } // Copy GVMap over to a standard value map. ValueToValueMapTy VM; for (auto I = GVMap.begin(), E = GVMap.end(); I != E; ++I) VM[I->first] = I->second; // Walk through the metadata section and update the debug information // associated with the global variables in the default address space. for (NamedMDNode &I : M.named_metadata()) { remapNamedMDNode(VM, &I); } // Walk through the global variable initializers, and replace any use of // original global variables in GVMap with a use of the corresponding copies // in GVMap. The copies need to be bitcast to the original global variable // types, as we cannot use cvta in global variable initializers. for (GVMapTy::iterator I = GVMap.begin(), E = GVMap.end(); I != E;) { GlobalVariable *GV = I->first; GlobalVariable *NewGV = I->second; // Remove GV from the map so that it can be RAUWed. Note that // DenseMap::erase() won't invalidate any iterators but this one. auto Next = std::next(I); GVMap.erase(I); I = Next; Constant *BitCastNewGV = ConstantExpr::getPointerCast(NewGV, GV->getType()); // At this point, the remaining uses of GV should be found only in global // variable initializers, as other uses have been already been removed // while walking through the instructions in function definitions. GV->replaceAllUsesWith(BitCastNewGV); std::string Name = GV->getName(); GV->eraseFromParent(); NewGV->setName(Name); } assert(GVMap.empty() && "Expected it to be empty by now"); return true; }
// This function replaces all global variables with new variables that have // trailing redzones. It also creates a function that poisons // redzones and inserts this function into llvm.global_ctors. bool AddressSanitizer::insertGlobalRedzones(Module &M) { SmallVector<GlobalVariable *, 16> GlobalsToChange; for (Module::GlobalListType::iterator G = M.global_begin(), E = M.global_end(); G != E; ++G) { if (ShouldInstrumentGlobal(G)) GlobalsToChange.push_back(G); } size_t n = GlobalsToChange.size(); if (n == 0) return false; // A global is described by a structure // size_t beg; // size_t size; // size_t size_with_redzone; // const char *name; // size_t has_dynamic_init; // We initialize an array of such structures and pass it to a run-time call. StructType *GlobalStructTy = StructType::get(IntptrTy, IntptrTy, IntptrTy, IntptrTy, IntptrTy, NULL); SmallVector<Constant *, 16> Initializers(n), DynamicInit; IRBuilder<> IRB(CtorInsertBefore); if (ClInitializers) FindDynamicInitializers(M); // The addresses of the first and last dynamically initialized globals in // this TU. Used in initialization order checking. Value *FirstDynamic = 0, *LastDynamic = 0; for (size_t i = 0; i < n; i++) { GlobalVariable *G = GlobalsToChange[i]; PointerType *PtrTy = cast<PointerType>(G->getType()); Type *Ty = PtrTy->getElementType(); uint64_t SizeInBytes = TD->getTypeAllocSize(Ty); uint64_t RightRedzoneSize = RedzoneSize + (RedzoneSize - (SizeInBytes % RedzoneSize)); Type *RightRedZoneTy = ArrayType::get(IRB.getInt8Ty(), RightRedzoneSize); // Determine whether this global should be poisoned in initialization. bool GlobalHasDynamicInitializer = HasDynamicInitializer(G); // Don't check initialization order if this global is blacklisted. GlobalHasDynamicInitializer &= !BL->isInInit(*G); StructType *NewTy = StructType::get(Ty, RightRedZoneTy, NULL); Constant *NewInitializer = ConstantStruct::get( NewTy, G->getInitializer(), Constant::getNullValue(RightRedZoneTy), NULL); SmallString<2048> DescriptionOfGlobal = G->getName(); DescriptionOfGlobal += " ("; DescriptionOfGlobal += M.getModuleIdentifier(); DescriptionOfGlobal += ")"; GlobalVariable *Name = createPrivateGlobalForString(M, DescriptionOfGlobal); // Create a new global variable with enough space for a redzone. GlobalVariable *NewGlobal = new GlobalVariable( M, NewTy, G->isConstant(), G->getLinkage(), NewInitializer, "", G, G->getThreadLocalMode()); NewGlobal->copyAttributesFrom(G); NewGlobal->setAlignment(RedzoneSize); Value *Indices2[2]; Indices2[0] = IRB.getInt32(0); Indices2[1] = IRB.getInt32(0); G->replaceAllUsesWith( ConstantExpr::getGetElementPtr(NewGlobal, Indices2, true)); NewGlobal->takeName(G); G->eraseFromParent(); Initializers[i] = ConstantStruct::get( GlobalStructTy, ConstantExpr::getPointerCast(NewGlobal, IntptrTy), ConstantInt::get(IntptrTy, SizeInBytes), ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize), ConstantExpr::getPointerCast(Name, IntptrTy), ConstantInt::get(IntptrTy, GlobalHasDynamicInitializer), NULL); // Populate the first and last globals declared in this TU. if (ClInitializers && GlobalHasDynamicInitializer) { LastDynamic = ConstantExpr::getPointerCast(NewGlobal, IntptrTy); if (FirstDynamic == 0) FirstDynamic = LastDynamic; } DEBUG(dbgs() << "NEW GLOBAL:\n" << *NewGlobal); } ArrayType *ArrayOfGlobalStructTy = ArrayType::get(GlobalStructTy, n); GlobalVariable *AllGlobals = new GlobalVariable( M, ArrayOfGlobalStructTy, false, GlobalVariable::PrivateLinkage, ConstantArray::get(ArrayOfGlobalStructTy, Initializers), ""); // Create calls for poisoning before initializers run and unpoisoning after. if (ClInitializers && FirstDynamic && LastDynamic) createInitializerPoisonCalls(M, FirstDynamic, LastDynamic); Function *AsanRegisterGlobals = checkInterfaceFunction(M.getOrInsertFunction( kAsanRegisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); AsanRegisterGlobals->setLinkage(Function::ExternalLinkage); IRB.CreateCall2(AsanRegisterGlobals, IRB.CreatePointerCast(AllGlobals, IntptrTy), ConstantInt::get(IntptrTy, n)); // We also need to unregister globals at the end, e.g. when a shared library // gets closed. Function *AsanDtorFunction = Function::Create( FunctionType::get(Type::getVoidTy(*C), false), GlobalValue::InternalLinkage, kAsanModuleDtorName, &M); BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction); IRBuilder<> IRB_Dtor(ReturnInst::Create(*C, AsanDtorBB)); Function *AsanUnregisterGlobals = checkInterfaceFunction(M.getOrInsertFunction( kAsanUnregisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); AsanUnregisterGlobals->setLinkage(Function::ExternalLinkage); IRB_Dtor.CreateCall2(AsanUnregisterGlobals, IRB.CreatePointerCast(AllGlobals, IntptrTy), ConstantInt::get(IntptrTy, n)); appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndCtorPriority); DEBUG(dbgs() << M); return true; }
// This function replaces all global variables with new variables that have // trailing redzones. It also creates a function that poisons // redzones and inserts this function into llvm.global_ctors. bool AddressSanitizer::insertGlobalRedzones(Module &M) { SmallVector<GlobalVariable *, 16> GlobalsToChange; for (Module::GlobalListType::iterator G = M.getGlobalList().begin(), E = M.getGlobalList().end(); G != E; ++G) { Type *Ty = cast<PointerType>(G->getType())->getElementType(); DEBUG(dbgs() << "GLOBAL: " << *G); if (!Ty->isSized()) continue; if (!G->hasInitializer()) continue; // Touch only those globals that will not be defined in other modules. // Don't handle ODR type linkages since other modules may be built w/o asan. if (G->getLinkage() != GlobalVariable::ExternalLinkage && G->getLinkage() != GlobalVariable::PrivateLinkage && G->getLinkage() != GlobalVariable::InternalLinkage) continue; // Two problems with thread-locals: // - The address of the main thread's copy can't be computed at link-time. // - Need to poison all copies, not just the main thread's one. if (G->isThreadLocal()) continue; // For now, just ignore this Alloca if the alignment is large. if (G->getAlignment() > RedzoneSize) continue; // Ignore all the globals with the names starting with "\01L_OBJC_". // Many of those are put into the .cstring section. The linker compresses // that section by removing the spare \0s after the string terminator, so // our redzones get broken. if ((G->getName().find("\01L_OBJC_") == 0) || (G->getName().find("\01l_OBJC_") == 0)) { DEBUG(dbgs() << "Ignoring \\01L_OBJC_* global: " << *G); continue; } if (G->hasSection()) { StringRef Section(G->getSection()); // Ignore the globals from the __OBJC section. The ObjC runtime assumes // those conform to /usr/lib/objc/runtime.h, so we can't add redzones to // them. if ((Section.find("__OBJC,") == 0) || (Section.find("__DATA, __objc_") == 0)) { DEBUG(dbgs() << "Ignoring ObjC runtime global: " << *G); continue; } // See http://code.google.com/p/address-sanitizer/issues/detail?id=32 // Constant CFString instances are compiled in the following way: // -- the string buffer is emitted into // __TEXT,__cstring,cstring_literals // -- the constant NSConstantString structure referencing that buffer // is placed into __DATA,__cfstring // Therefore there's no point in placing redzones into __DATA,__cfstring. // Moreover, it causes the linker to crash on OS X 10.7 if (Section.find("__DATA,__cfstring") == 0) { DEBUG(dbgs() << "Ignoring CFString: " << *G); continue; } } GlobalsToChange.push_back(G); } size_t n = GlobalsToChange.size(); if (n == 0) return false; // A global is described by a structure // size_t beg; // size_t size; // size_t size_with_redzone; // const char *name; // We initialize an array of such structures and pass it to a run-time call. StructType *GlobalStructTy = StructType::get(IntptrTy, IntptrTy, IntptrTy, IntptrTy, NULL); SmallVector<Constant *, 16> Initializers(n); IRBuilder<> IRB(CtorInsertBefore); for (size_t i = 0; i < n; i++) { GlobalVariable *G = GlobalsToChange[i]; PointerType *PtrTy = cast<PointerType>(G->getType()); Type *Ty = PtrTy->getElementType(); uint64_t SizeInBytes = TD->getTypeStoreSizeInBits(Ty) / 8; uint64_t RightRedzoneSize = RedzoneSize + (RedzoneSize - (SizeInBytes % RedzoneSize)); Type *RightRedZoneTy = ArrayType::get(IRB.getInt8Ty(), RightRedzoneSize); StructType *NewTy = StructType::get(Ty, RightRedZoneTy, NULL); Constant *NewInitializer = ConstantStruct::get( NewTy, G->getInitializer(), Constant::getNullValue(RightRedZoneTy), NULL); SmallString<2048> DescriptionOfGlobal = G->getName(); DescriptionOfGlobal += " ("; DescriptionOfGlobal += M.getModuleIdentifier(); DescriptionOfGlobal += ")"; GlobalVariable *Name = createPrivateGlobalForString(M, DescriptionOfGlobal); // Create a new global variable with enough space for a redzone. GlobalVariable *NewGlobal = new GlobalVariable( M, NewTy, G->isConstant(), G->getLinkage(), NewInitializer, "", G, G->isThreadLocal()); NewGlobal->copyAttributesFrom(G); NewGlobal->setAlignment(RedzoneSize); Value *Indices2[2]; Indices2[0] = IRB.getInt32(0); Indices2[1] = IRB.getInt32(0); G->replaceAllUsesWith( ConstantExpr::getGetElementPtr(NewGlobal, Indices2, true)); NewGlobal->takeName(G); G->eraseFromParent(); Initializers[i] = ConstantStruct::get( GlobalStructTy, ConstantExpr::getPointerCast(NewGlobal, IntptrTy), ConstantInt::get(IntptrTy, SizeInBytes), ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize), ConstantExpr::getPointerCast(Name, IntptrTy), NULL); DEBUG(dbgs() << "NEW GLOBAL:\n" << *NewGlobal); } ArrayType *ArrayOfGlobalStructTy = ArrayType::get(GlobalStructTy, n); GlobalVariable *AllGlobals = new GlobalVariable( M, ArrayOfGlobalStructTy, false, GlobalVariable::PrivateLinkage, ConstantArray::get(ArrayOfGlobalStructTy, Initializers), ""); Function *AsanRegisterGlobals = cast<Function>(M.getOrInsertFunction( kAsanRegisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); AsanRegisterGlobals->setLinkage(Function::ExternalLinkage); IRB.CreateCall2(AsanRegisterGlobals, IRB.CreatePointerCast(AllGlobals, IntptrTy), ConstantInt::get(IntptrTy, n)); // We also need to unregister globals at the end, e.g. when a shared library // gets closed. Function *AsanDtorFunction = Function::Create( FunctionType::get(Type::getVoidTy(*C), false), GlobalValue::InternalLinkage, kAsanModuleDtorName, &M); BasicBlock *AsanDtorBB = BasicBlock::Create(*C, "", AsanDtorFunction); IRBuilder<> IRB_Dtor(ReturnInst::Create(*C, AsanDtorBB)); Function *AsanUnregisterGlobals = cast<Function>(M.getOrInsertFunction( kAsanUnregisterGlobalsName, IRB.getVoidTy(), IntptrTy, IntptrTy, NULL)); AsanUnregisterGlobals->setLinkage(Function::ExternalLinkage); IRB_Dtor.CreateCall2(AsanUnregisterGlobals, IRB.CreatePointerCast(AllGlobals, IntptrTy), ConstantInt::get(IntptrTy, n)); appendToGlobalDtors(M, AsanDtorFunction, kAsanCtorAndCtorPriority); DEBUG(dbgs() << M); return true; }
GlobalVariable * InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) { GlobalVariable *NamePtr = Inc->getName(); auto It = ProfileDataMap.find(NamePtr); PerFunctionProfileData PD; if (It != ProfileDataMap.end()) { if (It->second.RegionCounters) return It->second.RegionCounters; PD = It->second; } // Move the name variable to the right section. Place them in a COMDAT group // if the associated function is a COMDAT. This will make sure that // only one copy of counters of the COMDAT function will be emitted after // linking. Function *Fn = Inc->getParent()->getParent(); Comdat *ProfileVarsComdat = nullptr; if (Fn->hasComdat()) ProfileVarsComdat = getOrCreateProfileComdat(*M, Inc); NamePtr->setSection(getNameSection()); NamePtr->setAlignment(1); NamePtr->setComdat(ProfileVarsComdat); uint64_t NumCounters = Inc->getNumCounters()->getZExtValue(); LLVMContext &Ctx = M->getContext(); ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(Ctx), NumCounters); // Create the counters variable. auto *CounterPtr = new GlobalVariable(*M, CounterTy, false, NamePtr->getLinkage(), Constant::getNullValue(CounterTy), getVarName(Inc, getInstrProfCountersVarPrefix())); CounterPtr->setVisibility(NamePtr->getVisibility()); CounterPtr->setSection(getCountersSection()); CounterPtr->setAlignment(8); CounterPtr->setComdat(ProfileVarsComdat); // Create data variable. auto *Int8PtrTy = Type::getInt8PtrTy(Ctx); auto *Int16Ty = Type::getInt16Ty(Ctx); auto *Int16ArrayTy = ArrayType::get(Int16Ty, IPVK_Last+1); Type *DataTypes[] = { #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) LLVMType, #include "llvm/ProfileData/InstrProfData.inc" }; auto *DataTy = StructType::get(Ctx, makeArrayRef(DataTypes)); Constant *FunctionAddr = shouldRecordFunctionAddr(Fn) ? ConstantExpr::getBitCast(Fn, Int8PtrTy) : ConstantPointerNull::get(Int8PtrTy); Constant *Int16ArrayVals[IPVK_Last+1]; for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind) Int16ArrayVals[Kind] = ConstantInt::get(Int16Ty, PD.NumValueSites[Kind]); Constant *DataVals[] = { #define INSTR_PROF_DATA(Type, LLVMType, Name, Init) Init, #include "llvm/ProfileData/InstrProfData.inc" }; auto *Data = new GlobalVariable(*M, DataTy, false, NamePtr->getLinkage(), ConstantStruct::get(DataTy, DataVals), getVarName(Inc, getInstrProfDataVarPrefix())); Data->setVisibility(NamePtr->getVisibility()); Data->setSection(getDataSection()); Data->setAlignment(INSTR_PROF_DATA_ALIGNMENT); Data->setComdat(ProfileVarsComdat); PD.RegionCounters = CounterPtr; PD.DataVar = Data; ProfileDataMap[NamePtr] = PD; // Mark the data variable as used so that it isn't stripped out. UsedVars.push_back(Data); return CounterPtr; }
bool runOnFunction(Function &F) override { if (F.hasFnAttribute("emit_llvm")) { Module *M = F.getParent(); static Regex R("4func.*$"); GlobalVariable *GV = M->getGlobalVariable(R.sub("2irE", F.getName()), true); if (GV != NULL) { string S; raw_string_ostream SO(S); F.print(SO); Constant *CDA = ConstantDataArray::getString(M->getContext(), SO.str()); GV->setInitializer(ConstantExpr::getBitCast(new GlobalVariable(*M, CDA->getType(), true, GV->getLinkage(), CDA), Type::getInt8PtrTy(M->getContext()))); return true; } } return false; }