[esan] Add calls from the ctor/dtor to the runtime library

Summary:
Adds createEsanInitToolGV for creating a tool-specific variable passed
to the runtime library.

Adds dtor "esan.module_dtor" and inserts calls from the dtor to
"__esan_exit" in the runtime library.

Updates the EfficiencySanitizer test.

Patch by Qin Zhao.

Reviewers: aizatsky

Subscribers: bruening, kcc, vitalybuka, eugenis, llvm-commits

Differential Revision: http://reviews.llvm.org/D20488

llvm-svn: 270627
diff --git a/llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp b/llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
index 8feadd2..6c47960 100644
--- a/llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp
@@ -59,8 +59,11 @@
 STATISTIC(NumAccessesWithIrregularSize,
           "Number of accesses with a size outside our targeted callout sizes");
 
+static const uint64_t EsanCtorAndDtorPriority = 0;
 static const char *const EsanModuleCtorName = "esan.module_ctor";
+static const char *const EsanModuleDtorName = "esan.module_dtor";
 static const char *const EsanInitName = "__esan_init";
+static const char *const EsanExitName = "__esan_exit";
 
 namespace {
 
@@ -90,6 +93,8 @@
 private:
   bool initOnModule(Module &M);
   void initializeCallbacks(Module &M);
+  GlobalVariable *createEsanInitToolGV(Module &M);
+  void createDestructor(Module &M, GlobalVariable *GV);
   bool runOnFunction(Function &F, Module &M);
   bool instrumentLoadOrStore(Instruction *I, const DataLayout &DL);
   bool instrumentMemIntrinsic(MemIntrinsic *MI);
@@ -115,6 +120,7 @@
   Function *EsanUnalignedLoadN, *EsanUnalignedStoreN;
   Function *MemmoveFn, *MemcpyFn, *MemsetFn;
   Function *EsanCtorFunction;
+  Function *EsanDtorFunction;
 };
 } // namespace
 
@@ -173,19 +179,50 @@
                             IRB.getInt32Ty(), IntptrTy, nullptr));
 }
 
+// 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;
+}
+
+void EfficiencySanitizer::createDestructor(Module &M, GlobalVariable *GV) {
+  EsanDtorFunction = Function::Create(FunctionType::get(Type::getVoidTy(*Ctx),
+                                                        false),
+                                      GlobalValue::InternalLinkage,
+                                      EsanModuleDtorName, &M);
+  ReturnInst::Create(*Ctx, BasicBlock::Create(*Ctx, "", EsanDtorFunction));
+  IRBuilder<> IRB_Dtor(EsanDtorFunction->getEntryBlock().getTerminator());
+  Function *EsanExit = checkSanitizerInterfaceFunction(
+      M.getOrInsertFunction(EsanExitName, IRB_Dtor.getVoidTy(),
+                            IntptrTy, nullptr));
+  EsanExit->setLinkage(Function::ExternalLinkage);
+  IRB_Dtor.CreateCall(EsanExit,
+                      {IRB_Dtor.CreatePointerCast(GV, IntptrTy)});
+  appendToGlobalDtors(M, EsanDtorFunction, EsanCtorAndDtorPriority);
+}
+
 bool EfficiencySanitizer::initOnModule(Module &M) {
   Ctx = &M.getContext();
   const DataLayout &DL = M.getDataLayout();
   IRBuilder<> IRB(M.getContext());
   IntegerType *OrdTy = IRB.getInt32Ty();
   IntptrTy = DL.getIntPtrType(M.getContext());
+  // Create the variable passed to EsanInit and EsanExit.
+  GlobalVariable *GV = createEsanInitToolGV(M);
+  // Constructor
   std::tie(EsanCtorFunction, std::ignore) = createSanitizerCtorAndInitFunctions(
-      M, EsanModuleCtorName, EsanInitName, /*InitArgTypes=*/{OrdTy},
+      M, EsanModuleCtorName, EsanInitName, /*InitArgTypes=*/{OrdTy, IntptrTy},
       /*InitArgs=*/{
-          ConstantInt::get(OrdTy, static_cast<int>(Options.ToolType))});
+        ConstantInt::get(OrdTy, static_cast<int>(Options.ToolType)),
+        ConstantExpr::getPointerCast(GV, IntptrTy)});
+  appendToGlobalCtors(M, EsanCtorFunction, EsanCtorAndDtorPriority);
 
-  appendToGlobalCtors(M, EsanCtorFunction, 0);
-
+  createDestructor(M, GV);
   return true;
 }
 
@@ -216,7 +253,7 @@
   SmallVector<Instruction *, 8> LoadsAndStores;
   SmallVector<Instruction *, 8> MemIntrinCalls;
   bool Res = false;
-  const DataLayout &DL = F.getParent()->getDataLayout();
+  const DataLayout &DL = M.getDataLayout();
 
   for (auto &BB : F) {
     for (auto &Inst : BB) {