Index: lib/Transforms/Instrumentation/EfficiencySanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/EfficiencySanitizer.cpp +++ lib/Transforms/Instrumentation/EfficiencySanitizer.cpp @@ -69,14 +69,13 @@ static EfficiencySanitizerOptions OverrideOptionsFromCL(EfficiencySanitizerOptions Options) { - if (ClToolCacheFrag) - Options.ToolType = EfficiencySanitizerOptions::ESAN_CacheFrag; - // Direct opt invocation with no params will have the default ESAN_None. // We run the default tool in that case. if (Options.ToolType == EfficiencySanitizerOptions::ESAN_None) Options.ToolType = EfficiencySanitizerOptions::ESAN_CacheFrag; + if (Options.ToolType == EfficiencySanitizerOptions::ESAN_CacheFrag) + ClToolCacheFrag = true; return Options; } @@ -93,6 +92,7 @@ private: bool initOnModule(Module &M); void initializeCallbacks(Module &M); + GlobalVariable *createCacheFragGV(Module &M); GlobalVariable *createEsanInitToolGV(Module &M); void createDestructor(Module &M, GlobalVariable *GV); bool runOnFunction(Function &F, Module &M); @@ -105,6 +105,9 @@ // Each tool has its own fastpath routine: bool instrumentFastpathCacheFrag(Instruction *I, const DataLayout &DL, Value *Addr, unsigned Alignment); + // Static help routines: + static GlobalVariable *createPrivateGlobalForString( + Module &M, StringRef Str, bool AllowMerging); EfficiencySanitizerOptions Options; LLVMContext *Ctx; @@ -137,6 +140,21 @@ return new EfficiencySanitizer(Options); } +// Create a constant for Str so that we can pass it to the run-time lib. +GlobalVariable *EfficiencySanitizer::createPrivateGlobalForString( + Module &M, StringRef Str, bool AllowMerging) { + Constant *StrConst = ConstantDataArray::getString(M.getContext(), Str); + // We use private linkage for module-local strings. If they can be merged + // with another one, we set the unnamed_addr attribute. + GlobalVariable *GV = + new GlobalVariable(M, StrConst->getType(), true, + GlobalValue::PrivateLinkage, StrConst, ""); + if (AllowMerging) + GV->setUnnamedAddr(true); + GV->setAlignment(1); // Strings may not be merged w/o setting align 1. + return GV; +} + void EfficiencySanitizer::initializeCallbacks(Module &M) { IRBuilder<> IRB(M.getContext()); // Initialize the callbacks. @@ -179,10 +197,42 @@ IRB.getInt32Ty(), IntptrTy, nullptr)); } +// Create the global variable for the cache-fragmentation tool. +GlobalVariable *EfficiencySanitizer::createCacheFragGV(Module &M) { + assert(ClToolCacheFrag); + + // This structure contains tool-specific information about each compilation + // unit (module) and is passed to the runtime library. + // This structure should be kept consistent with the CacheFragType in the + // runtime library cache_frag tool. + // struct CacheFragType { + // int ToolType; + // const char *UnitName; + // FIXME: add more entries for cache frag tool. + // }; + + IntegerType *Int32Ty = Type::getInt32Ty(*Ctx); + StructType *CacheFragType = + StructType::get(Int32Ty, IntptrTy, nullptr); + + // Compilation unit name. + GlobalVariable *UnitName = createPrivateGlobalForString( + M, M.getModuleIdentifier(), /*AllowMerging*/ true); + + GlobalVariable *CacheFragGV = new GlobalVariable( + M, CacheFragType, true, GlobalVariable::InternalLinkage, + ConstantStruct::get(CacheFragType, + ConstantInt::get(Int32Ty, Options.ToolType), + ConstantExpr::getPointerCast(UnitName, IntptrTy), + nullptr)); + return CacheFragGV; +} + // Create the tool-specific global variable passed to EsanInit and EsanExit. GlobalVariable *EfficiencySanitizer::createEsanInitToolGV(Module &M) { GlobalVariable *GV = nullptr; - // FIXME: create the tool specific global variable. + if (ClToolCacheFrag) + GV = createCacheFragGV(M); if (GV == nullptr) { GV = new GlobalVariable(M, IntptrTy, true, GlobalVariable::InternalLinkage, Constant::getNullValue(IntptrTy));