blob: 645ad23a9ccdb336bda87d786f11b938ae18ea81 [file] [log] [blame]
Alex Lorenzee024992014-08-04 18:41:51 +00001//===---- CoverageMappingGen.h - Coverage mapping generation ----*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Alex Lorenzee024992014-08-04 18:41:51 +00006//
7//===----------------------------------------------------------------------===//
8//
9// Instrumentation-based code coverage mapping generator
10//
11//===----------------------------------------------------------------------===//
12
Benjamin Kramer2f5db8b2014-08-13 16:25:19 +000013#ifndef LLVM_CLANG_LIB_CODEGEN_COVERAGEMAPPINGGEN_H
14#define LLVM_CLANG_LIB_CODEGEN_COVERAGEMAPPINGGEN_H
Alex Lorenzee024992014-08-04 18:41:51 +000015
16#include "clang/Basic/LLVM.h"
17#include "clang/Basic/SourceLocation.h"
Chandler Carruth0d9593d2015-01-14 11:29:14 +000018#include "clang/Lex/PPCallbacks.h"
Zequan Wub46176b2020-07-22 19:04:59 -070019#include "clang/Lex/Preprocessor.h"
Alex Lorenzee024992014-08-04 18:41:51 +000020#include "llvm/ADT/DenseMap.h"
21#include "llvm/IR/GlobalValue.h"
22#include "llvm/Support/raw_ostream.h"
23
24namespace clang {
25
26class LangOptions;
27class SourceManager;
28class FileEntry;
29class Preprocessor;
30class Decl;
31class Stmt;
32
Zequan Wub46176b2020-07-22 19:04:59 -070033struct SkippedRange {
34 SourceRange Range;
35 // The location of token before the skipped source range.
36 SourceLocation PrevTokLoc;
37 // The location of token after the skipped source range.
38 SourceLocation NextTokLoc;
39
40 SkippedRange(SourceRange Range, SourceLocation PrevTokLoc = SourceLocation(),
41 SourceLocation NextTokLoc = SourceLocation())
42 : Range(Range), PrevTokLoc(PrevTokLoc), NextTokLoc(NextTokLoc) {}
43};
44
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000045/// Stores additional source code information like skipped ranges which
Alex Lorenzee024992014-08-04 18:41:51 +000046/// is required by the coverage mapping generator and is obtained from
47/// the preprocessor.
Zequan Wu9caa3fbe2020-09-02 14:50:32 -070048class CoverageSourceInfo : public PPCallbacks,
49 public CommentHandler,
50 public EmptylineHandler {
Zequan Wub46176b2020-07-22 19:04:59 -070051 // A vector of skipped source ranges and PrevTokLoc with NextTokLoc.
52 std::vector<SkippedRange> SkippedRanges;
Zequan Wu9caa3fbe2020-09-02 14:50:32 -070053
54 SourceManager &SourceMgr;
Zequan Wub46176b2020-07-22 19:04:59 -070055
Alex Lorenzee024992014-08-04 18:41:51 +000056public:
Zequan Wub46176b2020-07-22 19:04:59 -070057 // Location of the token parsed before HandleComment is called. This is
58 // updated every time Preprocessor::Lex lexes a new token.
59 SourceLocation PrevTokLoc;
Zequan Wu9caa3fbe2020-09-02 14:50:32 -070060
61 CoverageSourceInfo(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {}
Zequan Wub46176b2020-07-22 19:04:59 -070062
63 std::vector<SkippedRange> &getSkippedRanges() { return SkippedRanges; }
Alex Lorenzee024992014-08-04 18:41:51 +000064
Zequan Wu9caa3fbe2020-09-02 14:50:32 -070065 void AddSkippedRange(SourceRange Range);
66
Vedant Kumar3919a502017-09-11 20:47:42 +000067 void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override;
Zequan Wub46176b2020-07-22 19:04:59 -070068
Zequan Wu9caa3fbe2020-09-02 14:50:32 -070069 void HandleEmptyline(SourceRange Range) override;
70
Zequan Wub46176b2020-07-22 19:04:59 -070071 bool HandleComment(Preprocessor &PP, SourceRange Range) override;
72
73 void updateNextTokLoc(SourceLocation Loc);
Alex Lorenzee024992014-08-04 18:41:51 +000074};
75
76namespace CodeGen {
77
78class CodeGenModule;
79
Adrian Prantl9fc8faf2018-05-09 01:00:01 +000080/// Organizes the cross-function state that is used while generating
Alex Lorenzee024992014-08-04 18:41:51 +000081/// code coverage mapping data.
82class CoverageMappingModuleGen {
Vedant Kumardd1ea9d2019-10-21 11:48:38 -070083 /// Information needed to emit a coverage record for a function.
84 struct FunctionInfo {
85 uint64_t NameHash;
86 uint64_t FuncHash;
87 std::string CoverageMapping;
88 bool IsUsed;
89 };
90
Alex Lorenzee024992014-08-04 18:41:51 +000091 CodeGenModule &CGM;
92 CoverageSourceInfo &SourceInfo;
93 llvm::SmallDenseMap<const FileEntry *, unsigned, 8> FileEntries;
Xinliang David Li2129ae52016-01-07 20:05:55 +000094 std::vector<llvm::Constant *> FunctionNames;
Vedant Kumardd1ea9d2019-10-21 11:48:38 -070095 std::vector<FunctionInfo> FunctionRecords;
96
97 /// Emit a function record.
98 void emitFunctionMappingRecord(const FunctionInfo &Info,
99 uint64_t FilenamesRef);
Alex Lorenzee024992014-08-04 18:41:51 +0000100
101public:
Zequan Wub46176b2020-07-22 19:04:59 -0700102 static CoverageSourceInfo *setUpCoverageCallbacks(Preprocessor &PP);
103
Reid Kleckner7cd595d2019-10-28 14:40:17 -0700104 CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo &SourceInfo)
Vedant Kumardd1ea9d2019-10-21 11:48:38 -0700105 : CGM(CGM), SourceInfo(SourceInfo) {}
Alex Lorenzee024992014-08-04 18:41:51 +0000106
107 CoverageSourceInfo &getSourceInfo() const {
108 return SourceInfo;
109 }
110
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000111 /// Add a function's coverage mapping record to the collection of the
Alex Lorenzee024992014-08-04 18:41:51 +0000112 /// function mapping records.
113 void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName,
Alex Lorenzf2cf38e2014-08-08 23:41:24 +0000114 StringRef FunctionNameValue,
Alex Lorenz1d45c5b2014-08-21 19:25:27 +0000115 uint64_t FunctionHash,
Xinliang David Li2129ae52016-01-07 20:05:55 +0000116 const std::string &CoverageMapping,
Xinliang David Li848da132016-01-19 00:49:06 +0000117 bool IsUsed = true);
Alex Lorenzee024992014-08-04 18:41:51 +0000118
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000119 /// Emit the coverage mapping data for a translation unit.
Alex Lorenzee024992014-08-04 18:41:51 +0000120 void emit();
121
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000122 /// Return the coverage mapping translation unit file id
Alex Lorenzee024992014-08-04 18:41:51 +0000123 /// for the given file.
124 unsigned getFileID(const FileEntry *File);
125};
126
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000127/// Organizes the per-function state that is used while generating
Alex Lorenzee024992014-08-04 18:41:51 +0000128/// code coverage mapping data.
129class CoverageMappingGen {
130 CoverageMappingModuleGen &CVM;
131 SourceManager &SM;
132 const LangOptions &LangOpts;
133 llvm::DenseMap<const Stmt *, unsigned> *CounterMap;
Alex Lorenzee024992014-08-04 18:41:51 +0000134
135public:
136 CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,
137 const LangOptions &LangOpts)
Justin Bognere5ee6c52014-10-02 16:44:01 +0000138 : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(nullptr) {}
Alex Lorenzee024992014-08-04 18:41:51 +0000139
140 CoverageMappingGen(CoverageMappingModuleGen &CVM, SourceManager &SM,
141 const LangOptions &LangOpts,
Justin Bognere5ee6c52014-10-02 16:44:01 +0000142 llvm::DenseMap<const Stmt *, unsigned> *CounterMap)
143 : CVM(CVM), SM(SM), LangOpts(LangOpts), CounterMap(CounterMap) {}
Alex Lorenzee024992014-08-04 18:41:51 +0000144
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000145 /// Emit the coverage mapping data which maps the regions of
Alex Lorenzee024992014-08-04 18:41:51 +0000146 /// code to counters that will be used to find the execution
147 /// counts for those regions.
148 void emitCounterMapping(const Decl *D, llvm::raw_ostream &OS);
149
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000150 /// Emit the coverage mapping data for an unused function.
Alex Lorenzee024992014-08-04 18:41:51 +0000151 /// It creates mapping regions with the counter of zero.
152 void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS);
153};
154
155} // end namespace CodeGen
156} // end namespace clang
157
158#endif