• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "LLVMWrapper.h"
2 #include "llvm/ProfileData/Coverage/CoverageMapping.h"
3 #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
4 #include "llvm/ProfileData/InstrProf.h"
5 #include "llvm/ADT/ArrayRef.h"
6 
7 #include <iostream>
8 
9 using namespace llvm;
10 
11 // FFI equivalent of enum `llvm::coverage::Counter::CounterKind`
12 // https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L97-L99
13 enum class LLVMRustCounterKind {
14   Zero = 0,
15   CounterValueReference = 1,
16   Expression = 2,
17 };
18 
19 // FFI equivalent of struct `llvm::coverage::Counter`
20 // https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L94-L149
21 struct LLVMRustCounter {
22   LLVMRustCounterKind CounterKind;
23   uint32_t ID;
24 };
25 
fromRust(LLVMRustCounter Counter)26 static coverage::Counter fromRust(LLVMRustCounter Counter) {
27   switch (Counter.CounterKind) {
28   case LLVMRustCounterKind::Zero:
29     return coverage::Counter::getZero();
30   case LLVMRustCounterKind::CounterValueReference:
31     return coverage::Counter::getCounter(Counter.ID);
32   case LLVMRustCounterKind::Expression:
33     return coverage::Counter::getExpression(Counter.ID);
34   }
35   report_fatal_error("Bad LLVMRustCounterKind!");
36 }
37 
38 // FFI equivalent of enum `llvm::coverage::CounterMappingRegion::RegionKind`
39 // https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L213-L234
40 enum class LLVMRustCounterMappingRegionKind {
41   CodeRegion = 0,
42   ExpansionRegion = 1,
43   SkippedRegion = 2,
44   GapRegion = 3,
45   BranchRegion = 4,
46 };
47 
48 static coverage::CounterMappingRegion::RegionKind
fromRust(LLVMRustCounterMappingRegionKind Kind)49 fromRust(LLVMRustCounterMappingRegionKind Kind) {
50   switch (Kind) {
51   case LLVMRustCounterMappingRegionKind::CodeRegion:
52     return coverage::CounterMappingRegion::CodeRegion;
53   case LLVMRustCounterMappingRegionKind::ExpansionRegion:
54     return coverage::CounterMappingRegion::ExpansionRegion;
55   case LLVMRustCounterMappingRegionKind::SkippedRegion:
56     return coverage::CounterMappingRegion::SkippedRegion;
57   case LLVMRustCounterMappingRegionKind::GapRegion:
58     return coverage::CounterMappingRegion::GapRegion;
59   case LLVMRustCounterMappingRegionKind::BranchRegion:
60     return coverage::CounterMappingRegion::BranchRegion;
61   }
62   report_fatal_error("Bad LLVMRustCounterMappingRegionKind!");
63 }
64 
65 // FFI equivalent of struct `llvm::coverage::CounterMappingRegion`
66 // https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L211-L304
67 struct LLVMRustCounterMappingRegion {
68   LLVMRustCounter Count;
69   LLVMRustCounter FalseCount;
70   uint32_t FileID;
71   uint32_t ExpandedFileID;
72   uint32_t LineStart;
73   uint32_t ColumnStart;
74   uint32_t LineEnd;
75   uint32_t ColumnEnd;
76   LLVMRustCounterMappingRegionKind Kind;
77 };
78 
79 // FFI equivalent of enum `llvm::coverage::CounterExpression::ExprKind`
80 // https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L154
81 enum class LLVMRustCounterExprKind {
82   Subtract = 0,
83   Add = 1,
84 };
85 
86 // FFI equivalent of struct `llvm::coverage::CounterExpression`
87 // https://github.com/rust-lang/llvm-project/blob/ea6fa9c2/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L151-L160
88 struct LLVMRustCounterExpression {
89   LLVMRustCounterExprKind Kind;
90   LLVMRustCounter LHS;
91   LLVMRustCounter RHS;
92 };
93 
94 static coverage::CounterExpression::ExprKind
fromRust(LLVMRustCounterExprKind Kind)95 fromRust(LLVMRustCounterExprKind Kind) {
96   switch (Kind) {
97   case LLVMRustCounterExprKind::Subtract:
98     return coverage::CounterExpression::Subtract;
99   case LLVMRustCounterExprKind::Add:
100     return coverage::CounterExpression::Add;
101   }
102   report_fatal_error("Bad LLVMRustCounterExprKind!");
103 }
104 
LLVMRustCoverageWriteFilenamesSectionToBuffer(const char * const Filenames[],size_t FilenamesLen,RustStringRef BufferOut)105 extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
106     const char* const Filenames[],
107     size_t FilenamesLen,
108     RustStringRef BufferOut) {
109   SmallVector<std::string,32> FilenameRefs;
110   for (size_t i = 0; i < FilenamesLen; i++) {
111     FilenameRefs.push_back(std::string(Filenames[i]));
112   }
113   auto FilenamesWriter =
114       coverage::CoverageFilenamesSectionWriter(ArrayRef<std::string>(FilenameRefs));
115   RawRustStringOstream OS(BufferOut);
116   FilenamesWriter.write(OS);
117 }
118 
LLVMRustCoverageWriteMappingToBuffer(const unsigned * VirtualFileMappingIDs,unsigned NumVirtualFileMappingIDs,const LLVMRustCounterExpression * RustExpressions,unsigned NumExpressions,const LLVMRustCounterMappingRegion * RustMappingRegions,unsigned NumMappingRegions,RustStringRef BufferOut)119 extern "C" void LLVMRustCoverageWriteMappingToBuffer(
120     const unsigned *VirtualFileMappingIDs,
121     unsigned NumVirtualFileMappingIDs,
122     const LLVMRustCounterExpression *RustExpressions,
123     unsigned NumExpressions,
124     const LLVMRustCounterMappingRegion *RustMappingRegions,
125     unsigned NumMappingRegions,
126     RustStringRef BufferOut) {
127   // Convert from FFI representation to LLVM representation.
128   SmallVector<coverage::CounterMappingRegion, 0> MappingRegions;
129   MappingRegions.reserve(NumMappingRegions);
130   for (const auto &Region : ArrayRef<LLVMRustCounterMappingRegion>(
131            RustMappingRegions, NumMappingRegions)) {
132     MappingRegions.emplace_back(
133         fromRust(Region.Count), fromRust(Region.FalseCount),
134         Region.FileID, Region.ExpandedFileID,
135         Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd,
136         fromRust(Region.Kind));
137   }
138 
139   std::vector<coverage::CounterExpression> Expressions;
140   Expressions.reserve(NumExpressions);
141   for (const auto &Expression :
142        ArrayRef<LLVMRustCounterExpression>(RustExpressions, NumExpressions)) {
143     Expressions.emplace_back(fromRust(Expression.Kind),
144                              fromRust(Expression.LHS),
145                              fromRust(Expression.RHS));
146   }
147 
148   auto CoverageMappingWriter = coverage::CoverageMappingWriter(
149       ArrayRef<unsigned>(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
150       Expressions,
151       MappingRegions);
152   RawRustStringOstream OS(BufferOut);
153   CoverageMappingWriter.write(OS);
154 }
155 
LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F,const char * FuncName)156 extern "C" LLVMValueRef LLVMRustCoverageCreatePGOFuncNameVar(LLVMValueRef F, const char *FuncName) {
157   StringRef FuncNameRef(FuncName);
158   return wrap(createPGOFuncNameVar(*cast<Function>(unwrap(F)), FuncNameRef));
159 }
160 
LLVMRustCoverageHashCString(const char * StrVal)161 extern "C" uint64_t LLVMRustCoverageHashCString(const char *StrVal) {
162   StringRef StrRef(StrVal);
163   return IndexedInstrProf::ComputeHash(StrRef);
164 }
165 
LLVMRustCoverageHashByteArray(const char * Bytes,unsigned NumBytes)166 extern "C" uint64_t LLVMRustCoverageHashByteArray(
167     const char *Bytes,
168     unsigned NumBytes) {
169   StringRef StrRef(Bytes, NumBytes);
170   return IndexedInstrProf::ComputeHash(StrRef);
171 }
172 
WriteSectionNameToString(LLVMModuleRef M,InstrProfSectKind SK,RustStringRef Str)173 static void WriteSectionNameToString(LLVMModuleRef M,
174                                      InstrProfSectKind SK,
175                                      RustStringRef Str) {
176   Triple TargetTriple(unwrap(M)->getTargetTriple());
177   auto name = getInstrProfSectionName(SK, TargetTriple.getObjectFormat());
178   RawRustStringOstream OS(Str);
179   OS << name;
180 }
181 
LLVMRustCoverageWriteMapSectionNameToString(LLVMModuleRef M,RustStringRef Str)182 extern "C" void LLVMRustCoverageWriteMapSectionNameToString(LLVMModuleRef M,
183                                                             RustStringRef Str) {
184   WriteSectionNameToString(M, IPSK_covmap, Str);
185 }
186 
LLVMRustCoverageWriteFuncSectionNameToString(LLVMModuleRef M,RustStringRef Str)187 extern "C" void LLVMRustCoverageWriteFuncSectionNameToString(LLVMModuleRef M,
188                                                              RustStringRef Str) {
189   WriteSectionNameToString(M, IPSK_covfun, Str);
190 }
191 
LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str)192 extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) {
193   auto name = getCoverageMappingVarName();
194   RawRustStringOstream OS(Str);
195   OS << name;
196 }
197 
LLVMRustCoverageMappingVersion()198 extern "C" uint32_t LLVMRustCoverageMappingVersion() {
199   return coverage::CovMapVersion::Version6;
200 }
201