Skip to content

Commit 39761b0

Browse files
authored
Rollup merge of #111382 - Zalathar:ffi, r=cuviper
Isolate coverage FFI type layouts from their underlying LLVM C++ types I noticed that several of the types used to send coverage information through FFI are not properly isolated from the layout of their corresponding C++ types in the LLVM API. This PR adds more explicitly-defined FFI struct/enum types in `CoverageMappingWrapper.cpp`, so that Rust source files in `rustc_codegen_ssa` and `rustc_codegen_llvm` aren't directly exposed to LLVM C++ types.
2 parents aa9adf4 + 9addf06 commit 39761b0

File tree

3 files changed

+118
-17
lines changed

3 files changed

+118
-17
lines changed

compiler/rustc_codegen_llvm/src/llvm/ffi.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -680,7 +680,9 @@ pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_v
680680
pub mod coverageinfo {
681681
use super::coverage_map;
682682

683-
/// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L209-L230)
683+
/// Corresponds to enum `llvm::coverage::CounterMappingRegion::RegionKind`.
684+
///
685+
/// Must match the layout of `LLVMRustCounterMappingRegionKind`.
684686
#[derive(Copy, Clone, Debug)]
685687
#[repr(C)]
686688
pub enum RegionKind {
@@ -714,7 +716,9 @@ pub mod coverageinfo {
714716
/// array", encoded separately), and source location (start and end positions of the represented
715717
/// code region).
716718
///
717-
/// Matches LLVMRustCounterMappingRegion.
719+
/// Corresponds to struct `llvm::coverage::CounterMappingRegion`.
720+
///
721+
/// Must match the layout of `LLVMRustCounterMappingRegion`.
718722
#[derive(Copy, Clone, Debug)]
719723
#[repr(C)]
720724
pub struct CounterMappingRegion {

compiler/rustc_codegen_ssa/src/coverageinfo/ffi.rs

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex};
22

3-
/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L95)
3+
/// Must match the layout of `LLVMRustCounterKind`.
44
#[derive(Copy, Clone, Debug)]
55
#[repr(C)]
66
pub enum CounterKind {
@@ -17,8 +17,10 @@ pub enum CounterKind {
1717
/// `instrprof.increment()`)
1818
/// * For `CounterKind::Expression`, `id` is the index into the coverage map's array of
1919
/// counter expressions.
20-
/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L102-L103)
21-
/// Important: The Rust struct layout (order and types of fields) must match its C++ counterpart.
20+
///
21+
/// Corresponds to struct `llvm::coverage::Counter`.
22+
///
23+
/// Must match the layout of `LLVMRustCounter`.
2224
#[derive(Copy, Clone, Debug)]
2325
#[repr(C)]
2426
pub struct Counter {
@@ -59,17 +61,19 @@ impl Counter {
5961
}
6062
}
6163

62-
/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L150)
64+
/// Corresponds to enum `llvm::coverage::CounterExpression::ExprKind`.
65+
///
66+
/// Must match the layout of `LLVMRustCounterExprKind`.
6367
#[derive(Copy, Clone, Debug)]
6468
#[repr(C)]
6569
pub enum ExprKind {
6670
Subtract = 0,
6771
Add = 1,
6872
}
6973

70-
/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/13.0-2021-09-30/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L151-L152)
71-
/// Important: The Rust struct layout (order and types of fields) must match its C++
72-
/// counterpart.
74+
/// Corresponds to struct `llvm::coverage::CounterExpression`.
75+
///
76+
/// Must match the layout of `LLVMRustCounterExpression`.
7377
#[derive(Copy, Clone, Debug)]
7478
#[repr(C)]
7579
pub struct CounterExpression {

compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp

+101-8
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,100 @@
88

99
using namespace llvm;
1010

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+
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
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
1167
struct LLVMRustCounterMappingRegion {
12-
coverage::Counter Count;
13-
coverage::Counter FalseCount;
68+
LLVMRustCounter Count;
69+
LLVMRustCounter FalseCount;
1470
uint32_t FileID;
1571
uint32_t ExpandedFileID;
1672
uint32_t LineStart;
1773
uint32_t ColumnStart;
1874
uint32_t LineEnd;
1975
uint32_t ColumnEnd;
20-
coverage::CounterMappingRegion::RegionKind Kind;
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,
2184
};
2285

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
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+
23105
extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
24106
const char* const Filenames[],
25107
size_t FilenamesLen,
@@ -37,9 +119,9 @@ extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
37119
extern "C" void LLVMRustCoverageWriteMappingToBuffer(
38120
const unsigned *VirtualFileMappingIDs,
39121
unsigned NumVirtualFileMappingIDs,
40-
const coverage::CounterExpression *Expressions,
122+
const LLVMRustCounterExpression *RustExpressions,
41123
unsigned NumExpressions,
42-
LLVMRustCounterMappingRegion *RustMappingRegions,
124+
const LLVMRustCounterMappingRegion *RustMappingRegions,
43125
unsigned NumMappingRegions,
44126
RustStringRef BufferOut) {
45127
// Convert from FFI representation to LLVM representation.
@@ -48,13 +130,24 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
48130
for (const auto &Region : ArrayRef<LLVMRustCounterMappingRegion>(
49131
RustMappingRegions, NumMappingRegions)) {
50132
MappingRegions.emplace_back(
51-
Region.Count, Region.FalseCount, Region.FileID, Region.ExpandedFileID,
133+
fromRust(Region.Count), fromRust(Region.FalseCount),
134+
Region.FileID, Region.ExpandedFileID,
52135
Region.LineStart, Region.ColumnStart, Region.LineEnd, Region.ColumnEnd,
53-
Region.Kind);
136+
fromRust(Region.Kind));
54137
}
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+
55148
auto CoverageMappingWriter = coverage::CoverageMappingWriter(
56149
ArrayRef<unsigned>(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
57-
ArrayRef<coverage::CounterExpression>(Expressions, NumExpressions),
150+
Expressions,
58151
MappingRegions);
59152
RawRustStringOstream OS(BufferOut);
60153
CoverageMappingWriter.write(OS);

0 commit comments

Comments
 (0)