diff options
| author | pawanbisht62 <36775517+pawanbisht62@users.noreply.github.com> | 2020-08-06 17:00:51 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-06 17:00:51 +0530 |
| commit | bac939edcf2137f625cfd7b56dfa4aa7b814868f (patch) | |
| tree | bbeab2a9f6869b0be809a8e7029a62a77c8e22da /src/librustc_codegen_ssa | |
| parent | fdfbd89946ca34d12eec658d111ce9a85cd23df0 (diff) | |
| parent | 3cfc7fe78eccc754b16981704a098d7bd520e2fd (diff) | |
Merge branch 'master' into feature/incorporate-tracing
Diffstat (limited to 'src/librustc_codegen_ssa')
| -rw-r--r-- | src/librustc_codegen_ssa/coverageinfo/map.rs | 184 | ||||
| -rw-r--r-- | src/librustc_codegen_ssa/coverageinfo/mod.rs | 1 | ||||
| -rw-r--r-- | src/librustc_codegen_ssa/mir/rvalue.rs | 167 | ||||
| -rw-r--r-- | src/librustc_codegen_ssa/traits/builder.rs | 1 | ||||
| -rw-r--r-- | src/librustc_codegen_ssa/traits/coverageinfo.rs | 15 |
5 files changed, 177 insertions, 191 deletions
diff --git a/src/librustc_codegen_ssa/coverageinfo/map.rs b/src/librustc_codegen_ssa/coverageinfo/map.rs index 72138065a90..7f6841f9daa 100644 --- a/src/librustc_codegen_ssa/coverageinfo/map.rs +++ b/src/librustc_codegen_ssa/coverageinfo/map.rs @@ -3,12 +3,8 @@ pub use super::ffi::*; use rustc_index::vec::IndexVec; use rustc_middle::ty::Instance; use rustc_middle::ty::TyCtxt; -use rustc_span::source_map::{Pos, SourceMap}; -use rustc_span::{BytePos, FileName, Loc, RealFileName}; -use std::cmp::{Ord, Ordering}; -use std::fmt; -use std::path::PathBuf; +use std::cmp::Ord; rustc_index::newtype_index! { pub struct ExpressionOperandId { @@ -38,127 +34,35 @@ rustc_index::newtype_index! { } } -#[derive(Clone, Debug)] -pub struct Region { - start: Loc, - end: Loc, -} - -impl Ord for Region { - fn cmp(&self, other: &Self) -> Ordering { - (&self.start.file.name, &self.start.line, &self.start.col, &self.end.line, &self.end.col) - .cmp(&( - &other.start.file.name, - &other.start.line, - &other.start.col, - &other.end.line, - &other.end.col, - )) - } -} - -impl PartialOrd for Region { - fn partial_cmp(&self, other: &Self) -> Option<Ordering> { - Some(self.cmp(other)) - } -} - -impl PartialEq for Region { - fn eq(&self, other: &Self) -> bool { - self.start.file.name == other.start.file.name - && self.start.line == other.start.line - && self.start.col == other.start.col - && self.end.line == other.end.line - && self.end.col == other.end.col - } -} - -impl Eq for Region {} - -impl fmt::Display for Region { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let (file_path, start_line, start_col, end_line, end_col) = self.file_start_and_end(); - write!(f, "{:?}:{}:{} - {}:{}", file_path, start_line, start_col, end_line, end_col) - } +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub struct Region<'tcx> { + pub file_name: &'tcx str, + pub start_line: u32, + pub start_col: u32, + pub end_line: u32, + pub end_col: u32, } -impl Region { - pub fn new(source_map: &SourceMap, start_byte_pos: u32, end_byte_pos: u32) -> Self { - let start = source_map.lookup_char_pos(BytePos::from_u32(start_byte_pos)); - let end = source_map.lookup_char_pos(BytePos::from_u32(end_byte_pos)); - assert_eq!( - start.file.name, end.file.name, - "Region start ({} -> {:?}) and end ({} -> {:?}) don't come from the same source file!", - start_byte_pos, start, end_byte_pos, end - ); - Self { start, end } - } - - pub fn file_start_and_end<'a>(&'a self) -> (&'a PathBuf, u32, u32, u32, u32) { - let start = &self.start; - let end = &self.end; - match &start.file.name { - FileName::Real(RealFileName::Named(path)) => ( - path, - start.line as u32, - start.col.to_u32() + 1, - end.line as u32, - end.col.to_u32() + 1, - ), - _ => { - bug!("start.file.name should be a RealFileName, but it was: {:?}", start.file.name) - } - } +impl<'tcx> Region<'tcx> { + pub fn new( + file_name: &'tcx str, + start_line: u32, + start_col: u32, + end_line: u32, + end_col: u32, + ) -> Self { + Self { file_name, start_line, start_col, end_line, end_col } } } #[derive(Clone, Debug)] -pub struct ExpressionRegion { +pub struct ExpressionRegion<'tcx> { lhs: ExpressionOperandId, op: ExprKind, rhs: ExpressionOperandId, - region: Region, + region: Region<'tcx>, } -// FIXME(richkadel): There seems to be a problem computing the file location in -// some cases. I need to investigate this more. When I generate and show coverage -// for the example binary in the crates.io crate `json5format`, I had a couple of -// notable problems: -// -// 1. I saw a lot of coverage spans in `llvm-cov show` highlighting regions in -// various comments (not corresponding to rustdoc code), indicating a possible -// problem with the byte_pos-to-source-map implementation. -// -// 2. And (perhaps not related) when I build the aforementioned example binary with: -// `RUST_FLAGS="-Zinstrument-coverage" cargo build --example formatjson5` -// and then run that binary with -// `LLVM_PROFILE_FILE="formatjson5.profraw" ./target/debug/examples/formatjson5 \ -// some.json5` for some reason the binary generates *TWO* `.profraw` files. One -// named `default.profraw` and the other named `formatjson5.profraw` (the expected -// name, in this case). -// -// 3. I think that if I eliminate regions within a function, their region_ids, -// referenced in expressions, will be wrong? I think the ids are implied by their -// array position in the final coverage map output (IIRC). -// -// 4. I suspect a problem (if not the only problem) is the SourceMap is wrong for some -// region start/end byte positions. Just like I couldn't get the function hash at -// intrinsic codegen time for external crate functions, I think the SourceMap I -// have here only applies to the local crate, and I know I have coverages that -// reference external crates. -// -// I still don't know if I fixed the hash problem correctly. If external crates -// implement the function, can't I use the coverage counters already compiled -// into those external crates? (Maybe not for generics and/or maybe not for -// macros... not sure. But I need to understand this better.) -// -// If the byte range conversion is wrong, fix it. But if it -// is right, then it is possible for the start and end to be in different files. -// Can I do something other than ignore coverages that span multiple files? -// -// If I can resolve this, remove the "Option<>" result type wrapper -// `regions_in_file_order()` accordingly. - /// Collects all of the coverage regions associated with (a) injected counters, (b) counter /// expressions (additions or subtraction), and (c) unreachable regions (always counted as zero), /// for a given Function. Counters and counter expressions have non-overlapping `id`s because they @@ -171,19 +75,17 @@ pub struct ExpressionRegion { /// only whitespace or comments). According to LLVM Code Coverage Mapping documentation, "A count /// for a gap area is only used as the line execution count if there are no other regions on a /// line." -pub struct FunctionCoverage<'a> { - source_map: &'a SourceMap, +pub struct FunctionCoverage<'tcx> { source_hash: u64, - counters: IndexVec<CounterValueReference, Option<Region>>, - expressions: IndexVec<InjectedExpressionIndex, Option<ExpressionRegion>>, - unreachable_regions: Vec<Region>, + counters: IndexVec<CounterValueReference, Option<Region<'tcx>>>, + expressions: IndexVec<InjectedExpressionIndex, Option<ExpressionRegion<'tcx>>>, + unreachable_regions: Vec<Region<'tcx>>, } -impl<'a> FunctionCoverage<'a> { - pub fn new<'tcx: 'a>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { +impl<'tcx> FunctionCoverage<'tcx> { + pub fn new(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { let coverageinfo = tcx.coverageinfo(instance.def_id()); Self { - source_map: tcx.sess.source_map(), source_hash: 0, // will be set with the first `add_counter()` counters: IndexVec::from_elem_n(None, coverageinfo.num_counters as usize), expressions: IndexVec::from_elem_n(None, coverageinfo.num_expressions as usize), @@ -194,20 +96,14 @@ impl<'a> FunctionCoverage<'a> { /// Adds a code region to be counted by an injected counter intrinsic. /// The source_hash (computed during coverage instrumentation) should also be provided, and /// should be the same for all counters in a given function. - pub fn add_counter( - &mut self, - source_hash: u64, - id: u32, - start_byte_pos: u32, - end_byte_pos: u32, - ) { + pub fn add_counter(&mut self, source_hash: u64, id: u32, region: Region<'tcx>) { if self.source_hash == 0 { self.source_hash = source_hash; } else { debug_assert_eq!(source_hash, self.source_hash); } self.counters[CounterValueReference::from(id)] - .replace(Region::new(self.source_map, start_byte_pos, end_byte_pos)) + .replace(region) .expect_none("add_counter called with duplicate `id`"); } @@ -231,8 +127,7 @@ impl<'a> FunctionCoverage<'a> { lhs: u32, op: ExprKind, rhs: u32, - start_byte_pos: u32, - end_byte_pos: u32, + region: Region<'tcx>, ) { let expression_id = ExpressionOperandId::from(id_descending_from_max); let lhs = ExpressionOperandId::from(lhs); @@ -240,18 +135,13 @@ impl<'a> FunctionCoverage<'a> { let expression_index = self.expression_index(expression_id); self.expressions[expression_index] - .replace(ExpressionRegion { - lhs, - op, - rhs, - region: Region::new(self.source_map, start_byte_pos, end_byte_pos), - }) + .replace(ExpressionRegion { lhs, op, rhs, region }) .expect_none("add_counter_expression called with duplicate `id_descending_from_max`"); } /// Add a region that will be marked as "unreachable", with a constant "zero counter". - pub fn add_unreachable_region(&mut self, start_byte_pos: u32, end_byte_pos: u32) { - self.unreachable_regions.push(Region::new(self.source_map, start_byte_pos, end_byte_pos)); + pub fn add_unreachable_region(&mut self, region: Region<'tcx>) { + self.unreachable_regions.push(region) } /// Return the source hash, generated from the HIR node structure, and used to indicate whether @@ -264,8 +154,8 @@ impl<'a> FunctionCoverage<'a> { /// associated `Regions` (from which the LLVM-specific `CoverageMapGenerator` will create /// `CounterMappingRegion`s. pub fn get_expressions_and_counter_regions( - &'a self, - ) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &'a Region)>) { + &'tcx self, + ) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &'tcx Region<'tcx>)>) { assert!(self.source_hash != 0); let counter_regions = self.counter_regions(); @@ -277,7 +167,7 @@ impl<'a> FunctionCoverage<'a> { (counter_expressions, counter_regions) } - fn counter_regions(&'a self) -> impl Iterator<Item = (Counter, &'a Region)> { + fn counter_regions(&'tcx self) -> impl Iterator<Item = (Counter, &'tcx Region<'tcx>)> { self.counters.iter_enumerated().filter_map(|(index, entry)| { // Option::map() will return None to filter out missing counters. This may happen // if, for example, a MIR-instrumented counter is removed during an optimization. @@ -288,8 +178,8 @@ impl<'a> FunctionCoverage<'a> { } fn expressions_with_regions( - &'a self, - ) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &'a Region)>) { + &'tcx self, + ) -> (Vec<CounterExpression>, impl Iterator<Item = (Counter, &'tcx Region<'tcx>)>) { let mut counter_expressions = Vec::with_capacity(self.expressions.len()); let mut expression_regions = Vec::with_capacity(self.expressions.len()); let mut new_indexes = @@ -350,7 +240,7 @@ impl<'a> FunctionCoverage<'a> { (counter_expressions, expression_regions.into_iter()) } - fn unreachable_regions(&'a self) -> impl Iterator<Item = (Counter, &'a Region)> { + fn unreachable_regions(&'tcx self) -> impl Iterator<Item = (Counter, &'tcx Region<'tcx>)> { self.unreachable_regions.iter().map(|region| (Counter::zero(), region)) } diff --git a/src/librustc_codegen_ssa/coverageinfo/mod.rs b/src/librustc_codegen_ssa/coverageinfo/mod.rs index 1f0ffd289b1..ff794a75c36 100644 --- a/src/librustc_codegen_ssa/coverageinfo/mod.rs +++ b/src/librustc_codegen_ssa/coverageinfo/mod.rs @@ -2,3 +2,4 @@ pub mod ffi; pub mod map; pub use map::ExprKind; +pub use map::Region; diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 9c108998bc9..77e94fe3d0a 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -11,7 +11,7 @@ use rustc_apfloat::{ieee, Float, Round, Status}; use rustc_hir::lang_items::ExchangeMallocFnLangItem; use rustc_middle::mir; use rustc_middle::ty::cast::{CastTy, IntTy}; -use rustc_middle::ty::layout::HasTyCtxt; +use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::symbol::sym; @@ -369,10 +369,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.inttoptr(usize_llval, ll_t_out) } (CastTy::Float, CastTy::Int(IntTy::I)) => { - cast_float_to_int(&mut bx, true, llval, ll_t_in, ll_t_out) + cast_float_to_int(&mut bx, true, llval, ll_t_in, ll_t_out, cast) } (CastTy::Float, CastTy::Int(_)) => { - cast_float_to_int(&mut bx, false, llval, ll_t_in, ll_t_out) + cast_float_to_int(&mut bx, false, llval, ll_t_in, ll_t_out, cast) } _ => bug!("unsupported cast: {:?} to {:?}", operand.layout.ty, cast.ty), }; @@ -772,6 +772,7 @@ fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( x: Bx::Value, float_ty: Bx::Type, int_ty: Bx::Type, + int_layout: TyAndLayout<'tcx>, ) -> Bx::Value { if let Some(false) = bx.cx().sess().opts.debugging_opts.saturating_float_casts { return if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; @@ -782,8 +783,6 @@ fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( return try_sat_result; } - let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; - let int_width = bx.cx().int_width(int_ty); let float_width = bx.cx().float_width(float_ty); // LLVM's fpto[su]i returns undef when the input x is infinite, NaN, or does not fit into the @@ -870,36 +869,138 @@ fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // int_ty::MIN and therefore the return value of int_ty::MIN is correct. // QED. - // Step 1 was already performed above. - - // Step 2: We use two comparisons and two selects, with %s1 being the result: - // %less_or_nan = fcmp ult %x, %f_min - // %greater = fcmp olt %x, %f_max - // %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result - // %s1 = select %greater, int_ty::MAX, %s0 - // Note that %less_or_nan uses an *unordered* comparison. This comparison is true if the - // operands are not comparable (i.e., if x is NaN). The unordered comparison ensures that s1 - // becomes int_ty::MIN if x is NaN. - // Performance note: Unordered comparison can be lowered to a "flipped" comparison and a - // negation, and the negation can be merged into the select. Therefore, it not necessarily any - // more expensive than a ordered ("normal") comparison. Whether these optimizations will be - // performed is ultimately up to the backend, but at least x86 does perform them. - let less_or_nan = bx.fcmp(RealPredicate::RealULT, x, f_min); - let greater = bx.fcmp(RealPredicate::RealOGT, x, f_max); let int_max = bx.cx().const_uint_big(int_ty, int_max(signed, int_width)); let int_min = bx.cx().const_uint_big(int_ty, int_min(signed, int_width) as u128); - let s0 = bx.select(less_or_nan, int_min, fptosui_result); - let s1 = bx.select(greater, int_max, s0); - - // Step 3: NaN replacement. - // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN. - // Therefore we only need to execute this step for signed integer types. - if signed { - // LLVM has no isNaN predicate, so we use (x == x) instead - let zero = bx.cx().const_uint(int_ty, 0); - let cmp = bx.fcmp(RealPredicate::RealOEQ, x, x); - bx.select(cmp, s1, zero) + let zero = bx.cx().const_uint(int_ty, 0); + + // The codegen here differs quite a bit depending on whether our builder's + // `fptosi` and `fptoui` instructions may trap for out-of-bounds values. If + // they don't trap then we can start doing everything inline with a + // `select` instruction because it's ok to execute `fptosi` and `fptoui` + // even if we don't use the results. + if !bx.fptosui_may_trap(x, int_ty) { + // Step 1 ... + let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; + let less_or_nan = bx.fcmp(RealPredicate::RealULT, x, f_min); + let greater = bx.fcmp(RealPredicate::RealOGT, x, f_max); + + // Step 2: We use two comparisons and two selects, with %s1 being the + // result: + // %less_or_nan = fcmp ult %x, %f_min + // %greater = fcmp olt %x, %f_max + // %s0 = select %less_or_nan, int_ty::MIN, %fptosi_result + // %s1 = select %greater, int_ty::MAX, %s0 + // Note that %less_or_nan uses an *unordered* comparison. This + // comparison is true if the operands are not comparable (i.e., if x is + // NaN). The unordered comparison ensures that s1 becomes int_ty::MIN if + // x is NaN. + // + // Performance note: Unordered comparison can be lowered to a "flipped" + // comparison and a negation, and the negation can be merged into the + // select. Therefore, it not necessarily any more expensive than a + // ordered ("normal") comparison. Whether these optimizations will be + // performed is ultimately up to the backend, but at least x86 does + // perform them. + let s0 = bx.select(less_or_nan, int_min, fptosui_result); + let s1 = bx.select(greater, int_max, s0); + + // Step 3: NaN replacement. + // For unsigned types, the above step already yielded int_ty::MIN == 0 if x is NaN. + // Therefore we only need to execute this step for signed integer types. + if signed { + // LLVM has no isNaN predicate, so we use (x == x) instead + let cmp = bx.fcmp(RealPredicate::RealOEQ, x, x); + bx.select(cmp, s1, zero) + } else { + s1 + } } else { - s1 + // In this case we cannot execute `fptosi` or `fptoui` and then later + // discard the result. The builder is telling us that these instructions + // will trap on out-of-bounds values, so we need to use basic blocks and + // control flow to avoid executing the `fptosi` and `fptoui` + // instructions. + // + // The general idea of what we're constructing here is, for f64 -> i32: + // + // ;; block so far... %0 is the argument + // %result = alloca i32, align 4 + // %inbound_lower = fcmp oge double %0, 0xC1E0000000000000 + // %inbound_upper = fcmp ole double %0, 0x41DFFFFFFFC00000 + // ;; match (inbound_lower, inbound_upper) { + // ;; (true, true) => %0 can be converted without trapping + // ;; (false, false) => %0 is a NaN + // ;; (true, false) => %0 is too large + // ;; (false, true) => %0 is too small + // ;; } + // ;; + // ;; The (true, true) check, go to %convert if so. + // %inbounds = and i1 %inbound_lower, %inbound_upper + // br i1 %inbounds, label %convert, label %specialcase + // + // convert: + // %cvt = call i32 @llvm.wasm.trunc.signed.i32.f64(double %0) + // store i32 %cvt, i32* %result, align 4 + // br label %done + // + // specialcase: + // ;; Handle the cases where the number is NaN, too large or too small + // + // ;; Either (true, false) or (false, true) + // %is_not_nan = or i1 %inbound_lower, %inbound_upper + // ;; Figure out which saturated value we are interested in if not `NaN` + // %saturated = select i1 %inbound_lower, i32 2147483647, i32 -2147483648 + // ;; Figure out between saturated and NaN representations + // %result_nan = select i1 %is_not_nan, i32 %saturated, i32 0 + // store i32 %result_nan, i32* %result, align 4 + // br label %done + // + // done: + // %r = load i32, i32* %result, align 4 + // ;; ... + let done = bx.build_sibling_block("float_cast_done"); + let mut convert = bx.build_sibling_block("float_cast_convert"); + let mut specialcase = bx.build_sibling_block("float_cast_specialcase"); + + let result = PlaceRef::alloca(bx, int_layout); + result.storage_live(bx); + + // Use control flow to figure out whether we can execute `fptosi` in a + // basic block, or whether we go to a different basic block to implement + // the saturating logic. + let inbound_lower = bx.fcmp(RealPredicate::RealOGE, x, f_min); + let inbound_upper = bx.fcmp(RealPredicate::RealOLE, x, f_max); + let inbounds = bx.and(inbound_lower, inbound_upper); + bx.cond_br(inbounds, convert.llbb(), specialcase.llbb()); + + // Translation of the `convert` basic block + let cvt = if signed { convert.fptosi(x, int_ty) } else { convert.fptoui(x, int_ty) }; + convert.store(cvt, result.llval, result.align); + convert.br(done.llbb()); + + // Translation of the `specialcase` basic block. Note that like above + // we try to be a bit clever here for unsigned conversions. In those + // cases the `int_min` is zero so we don't need two select instructions, + // just one to choose whether we need `int_max` or not. If + // `inbound_lower` is true then we're guaranteed to not be `NaN` and + // since we're greater than zero we must be saturating to `int_max`. If + // `inbound_lower` is false then we're either NaN or less than zero, so + // we saturate to zero. + let result_nan = if signed { + let is_not_nan = specialcase.or(inbound_lower, inbound_upper); + let saturated = specialcase.select(inbound_lower, int_max, int_min); + specialcase.select(is_not_nan, saturated, zero) + } else { + specialcase.select(inbound_lower, int_max, int_min) + }; + specialcase.store(result_nan, result.llval, result.align); + specialcase.br(done.llbb()); + + // Translation of the `done` basic block, positioning ourselves to + // continue from that point as well. + *bx = done; + let ret = bx.load(result.llval, result.align); + result.storage_dead(bx); + ret } } diff --git a/src/librustc_codegen_ssa/traits/builder.rs b/src/librustc_codegen_ssa/traits/builder.rs index 65eb70e173e..4e11ef5fd6e 100644 --- a/src/librustc_codegen_ssa/traits/builder.rs +++ b/src/librustc_codegen_ssa/traits/builder.rs @@ -160,6 +160,7 @@ pub trait BuilderMethods<'a, 'tcx>: fn sext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn fptoui_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option<Self::Value>; fn fptosi_sat(&mut self, val: Self::Value, dest_ty: Self::Type) -> Option<Self::Value>; + fn fptosui_may_trap(&self, val: Self::Value, dest_ty: Self::Type) -> bool; fn fptoui(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn fptosi(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn uitofp(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; diff --git a/src/librustc_codegen_ssa/traits/coverageinfo.rs b/src/librustc_codegen_ssa/traits/coverageinfo.rs index db1d86c974e..2b5878f46bc 100644 --- a/src/librustc_codegen_ssa/traits/coverageinfo.rs +++ b/src/librustc_codegen_ssa/traits/coverageinfo.rs @@ -1,5 +1,5 @@ use super::BackendTypes; -use crate::coverageinfo::ExprKind; +use crate::coverageinfo::{ExprKind, Region}; use rustc_middle::ty::Instance; pub trait CoverageInfoMethods: BackendTypes { @@ -12,8 +12,7 @@ pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { instance: Instance<'tcx>, function_source_hash: u64, index: u32, - start_byte_pos: u32, - end_byte_pos: u32, + region: Region<'tcx>, ); fn add_counter_expression_region( @@ -23,14 +22,8 @@ pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes { lhs: u32, op: ExprKind, rhs: u32, - start_byte_pos: u32, - end_byte_pos: u32, + region: Region<'tcx>, ); - fn add_unreachable_region( - &mut self, - instance: Instance<'tcx>, - start_byte_pos: u32, - end_byte_pos: u32, - ); + fn add_unreachable_region(&mut self, instance: Instance<'tcx>, region: Region<'tcx>); } |
