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