aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/llvm12/lib/Transforms/Utils/SanitizerStats.cpp
blob: acecebe646c981575d2f12ee1ff3de496df4a13f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//===- SanitizerStats.cpp - Sanitizer statistics gathering ----------------===// 
// 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
// See https://llvm.org/LICENSE.txt for license information. 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
// 
//===----------------------------------------------------------------------===// 
// 
// Implements code generation for sanitizer statistics gathering. 
// 
//===----------------------------------------------------------------------===// 
 
#include "llvm/Transforms/Utils/SanitizerStats.h" 
#include "llvm/ADT/Triple.h" 
#include "llvm/IR/Constants.h" 
#include "llvm/IR/DerivedTypes.h" 
#include "llvm/IR/GlobalVariable.h" 
#include "llvm/IR/IRBuilder.h" 
#include "llvm/IR/Module.h" 
#include "llvm/Transforms/Utils/ModuleUtils.h" 
 
using namespace llvm; 
 
SanitizerStatReport::SanitizerStatReport(Module *M) : M(M) { 
  StatTy = ArrayType::get(Type::getInt8PtrTy(M->getContext()), 2); 
  EmptyModuleStatsTy = makeModuleStatsTy(); 
 
  ModuleStatsGV = new GlobalVariable(*M, EmptyModuleStatsTy, false, 
                                     GlobalValue::InternalLinkage, nullptr); 
} 
 
ArrayType *SanitizerStatReport::makeModuleStatsArrayTy() { 
  return ArrayType::get(StatTy, Inits.size()); 
} 
 
StructType *SanitizerStatReport::makeModuleStatsTy() { 
  return StructType::get(M->getContext(), {Type::getInt8PtrTy(M->getContext()), 
                                           Type::getInt32Ty(M->getContext()), 
                                           makeModuleStatsArrayTy()}); 
} 
 
void SanitizerStatReport::create(IRBuilder<> &B, SanitizerStatKind SK) { 
  Function *F = B.GetInsertBlock()->getParent(); 
  Module *M = F->getParent(); 
  PointerType *Int8PtrTy = B.getInt8PtrTy(); 
  IntegerType *IntPtrTy = B.getIntPtrTy(M->getDataLayout()); 
  ArrayType *StatTy = ArrayType::get(Int8PtrTy, 2); 
 
  Inits.push_back(ConstantArray::get( 
      StatTy, 
      {Constant::getNullValue(Int8PtrTy), 
       ConstantExpr::getIntToPtr( 
           ConstantInt::get(IntPtrTy, uint64_t(SK) << (IntPtrTy->getBitWidth() - 
                                                       kSanitizerStatKindBits)), 
           Int8PtrTy)})); 
 
  FunctionType *StatReportTy = 
      FunctionType::get(B.getVoidTy(), Int8PtrTy, false); 
  FunctionCallee StatReport = 
      M->getOrInsertFunction("__sanitizer_stat_report", StatReportTy); 
 
  auto InitAddr = ConstantExpr::getGetElementPtr( 
      EmptyModuleStatsTy, ModuleStatsGV, 
      ArrayRef<Constant *>{ 
          ConstantInt::get(IntPtrTy, 0), ConstantInt::get(B.getInt32Ty(), 2), 
          ConstantInt::get(IntPtrTy, Inits.size() - 1), 
      }); 
  B.CreateCall(StatReport, ConstantExpr::getBitCast(InitAddr, Int8PtrTy)); 
} 
 
void SanitizerStatReport::finish() { 
  if (Inits.empty()) { 
    ModuleStatsGV->eraseFromParent(); 
    return; 
  } 
 
  PointerType *Int8PtrTy = Type::getInt8PtrTy(M->getContext()); 
  IntegerType *Int32Ty = Type::getInt32Ty(M->getContext()); 
  Type *VoidTy = Type::getVoidTy(M->getContext()); 
 
  // Create a new ModuleStatsGV to replace the old one. We can't just set the 
  // old one's initializer because its type is different. 
  auto NewModuleStatsGV = new GlobalVariable( 
      *M, makeModuleStatsTy(), false, GlobalValue::InternalLinkage, 
      ConstantStruct::getAnon( 
          {Constant::getNullValue(Int8PtrTy), 
           ConstantInt::get(Int32Ty, Inits.size()), 
           ConstantArray::get(makeModuleStatsArrayTy(), Inits)})); 
  ModuleStatsGV->replaceAllUsesWith( 
      ConstantExpr::getBitCast(NewModuleStatsGV, ModuleStatsGV->getType())); 
  ModuleStatsGV->eraseFromParent(); 
 
  // Create a global constructor to register NewModuleStatsGV. 
  auto F = Function::Create(FunctionType::get(VoidTy, false), 
                            GlobalValue::InternalLinkage, "", M); 
  auto BB = BasicBlock::Create(M->getContext(), "", F); 
  IRBuilder<> B(BB); 
 
  FunctionType *StatInitTy = FunctionType::get(VoidTy, Int8PtrTy, false); 
  FunctionCallee StatInit = 
      M->getOrInsertFunction("__sanitizer_stat_init", StatInitTy); 
 
  B.CreateCall(StatInit, ConstantExpr::getBitCast(NewModuleStatsGV, Int8PtrTy)); 
  B.CreateRetVoid(); 
 
  appendToGlobalCtors(*M, F, 0); 
}