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,7 +130,8 @@ private: bool initOnModule(Module &M); void initializeCallbacks(Module &M); - GlobalVariable *createEsanInitToolGV(Module &M); + GlobalVariable *createCacheFragInfoGV(Module &M, Constant *UnitName); + GlobalVariable *createEsanInitToolInfoGV(Module &M); void createDestructor(Module &M, GlobalVariable *GV); bool runOnFunction(Function &F, Module &M); bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL); @@ -204,15 +220,58 @@ IRB.getInt32Ty(), IntptrTy, nullptr)); } +// Create the global variable for the cache-fragmentation tool. +GlobalVariable *EfficiencySanitizer::createCacheFragInfoGV( + Module &M, Constant *UnitName) { + assert(Options.ToolType == EfficiencySanitizerOptions::ESAN_CacheFrag); + // Create the cache-fragmentation specific variable. + // This structure should be kept consistent with the CacheFragInfo struct + // in the runtime library. + // struct CacheFragInfo { + // const char *UnitName; + // ... + // }; + // FIXME: expand CacheFragInfo. + auto *Int8PtrTy = Type::getInt8PtrTy(*Ctx); + // We specify the struct type upfront instead of using anonymous struct + // for better error check. + auto *CacheFragInfoTy = StructType::get(Int8PtrTy, nullptr); + auto *CacheFragInfoGV = new GlobalVariable( + M, CacheFragInfoTy, true, GlobalVariable::InternalLinkage, + ConstantStruct::get(CacheFragInfoTy, + UnitName, + nullptr)); + return CacheFragInfoGV; +} + // 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; +GlobalVariable *EfficiencySanitizer::createEsanInitToolInfoGV(Module &M) { + // This structure contains tool-specific information about each compilation + // unit (module) and is passed to the runtime library. + + auto *Int8PtrTy = Type::getInt8PtrTy(*Ctx); + // Compilation unit name. + auto *UnitName = ConstantExpr::getPointerCast( + createPrivateGlobalForString(M, M.getModuleIdentifier(), true), + Int8PtrTy); + + // Create the tool-specific variable. + if (Options.ToolType == EfficiencySanitizerOptions::ESAN_CacheFrag) + return createCacheFragInfoGV(M, UnitName); + + // Create the default general variable. + // This structure should be kept consistent with the ToolInfo struct + // in the runtime library. + // struct ToolInfo { + // const char *UnitName; + // }; + auto *ToolInfoTy = StructType::get(Int8PtrTy, nullptr); + auto *ToolInfoGV = new GlobalVariable(M, ToolInfoTy, true, + GlobalVariable::InternalLinkage, + ConstantStruct::get(ToolInfoTy, + UnitName, + nullptr)); + return ToolInfoGV; } void EfficiencySanitizer::createDestructor(Module &M, GlobalVariable *GV) { @@ -238,7 +297,7 @@ IntegerType *OrdTy = IRB.getInt32Ty(); IntptrTy = DL.getIntPtrType(M.getContext()); // Create the variable passed to EsanInit and EsanExit. - GlobalVariable *GV = createEsanInitToolGV(M); + GlobalVariable *GV = createEsanInitToolInfoGV(M); // Constructor std::tie(EsanCtorFunction, std::ignore) = createSanitizerCtorAndInitFunctions( M, EsanModuleCtorName, EsanInitName, /*InitArgTypes=*/{OrdTy, IntptrTy},