Index: lib/Transforms/Instrumentation/EfficiencySanitizer.cpp =================================================================== --- lib/Transforms/Instrumentation/EfficiencySanitizer.cpp +++ lib/Transforms/Instrumentation/EfficiencySanitizer.cpp @@ -102,6 +102,21 @@ return Options; } +// Create a constant for Str so that we can pass it to the run-time lib. +static GlobalVariable *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; +} + /// EfficiencySanitizer: instrument each module to find performance issues. class EfficiencySanitizer : public ModulePass { public: @@ -115,6 +130,7 @@ private: bool initOnModule(Module &M); void initializeCallbacks(Module &M); + void createCacheFragGV(Module &M, SmallVector &ToolInfoVec); GlobalVariable *createEsanInitToolGV(Module &M); void createDestructor(Module &M, GlobalVariable *GV); bool runOnFunction(Function &F, Module &M); @@ -204,15 +220,39 @@ IRB.getInt32Ty(), IntptrTy, nullptr)); } +// Create the global variable for the cache-fragmentation tool. +void EfficiencySanitizer::createCacheFragGV( + Module &M, SmallVector &ToolInfoVec) { + assert(Options.ToolType == EfficiencySanitizerOptions::ESAN_CacheFrag); + // FIXME: expand ToolInfoVec for the cache-fragmentation tool. +} + // 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 (GV == nullptr) { - GV = new GlobalVariable(M, IntptrTy, true, GlobalVariable::InternalLinkage, - Constant::getNullValue(IntptrTy)); - } - return GV; + // 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 tool-specific struct + // in the runtime library. + // struct ToolInfo { + // const char *UnitName; + // // expanding for the specific tool. + // ... + // }; + SmallVector ToolInfoVec; + // Compilation unit name. + ToolInfoVec.push_back( + ConstantExpr::getPointerCast( + createPrivateGlobalForString(M, M.getModuleIdentifier(), true), + Type::getInt8PtrTy(*Ctx))); + // Expanding ToolInfo for the specific tool. + if (Options.ToolType == EfficiencySanitizerOptions::ESAN_CacheFrag) + createCacheFragGV(M, ToolInfoVec); + // Create the global variable. + Constant *ToolInfo = ConstantStruct::getAnon(ToolInfoVec); + auto *ToolInfoGV = new GlobalVariable(M, ToolInfo->getType(), true, + GlobalVariable::InternalLinkage, + ToolInfo); + return ToolInfoGV; } void EfficiencySanitizer::createDestructor(Module &M, GlobalVariable *GV) {