Skip to content

Commit f3fc94f

Browse files
committed
Fix #[track_caller] with MIR inlining
1 parent f449c0d commit f3fc94f

File tree

5 files changed

+95
-61
lines changed

5 files changed

+95
-61
lines changed

scripts/test_rustc_tests.sh

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ rm src/test/ui/type-alias-impl-trait/assoc-projection-ice.rs # produces ICE
105105

106106
rm src/test/ui/simd/intrinsic/generic-reduction-pass.rs # simd_reduce_add_unordered doesn't accept an accumulator for integer vectors
107107

108-
rm src/test/ui/rfc-2091-track-caller/intrinsic-wrapper.rs # wrong result from `Location::caller()`
109-
110108
# bugs in the test suite
111109
# ======================
112110
rm src/test/ui/backtrace.rs # TODO warning

src/abi/mod.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ fn codegen_call_argument_operand<'tcx>(
309309

310310
pub(crate) fn codegen_terminator_call<'tcx>(
311311
fx: &mut FunctionCx<'_, '_, 'tcx>,
312-
span: Span,
312+
source_info: mir::SourceInfo,
313313
func: &Operand<'tcx>,
314314
args: &[Operand<'tcx>],
315315
mir_dest: Option<(Place<'tcx>, BasicBlock)>,
@@ -340,7 +340,13 @@ pub(crate) fn codegen_terminator_call<'tcx>(
340340

341341
match instance.def {
342342
InstanceDef::Intrinsic(_) => {
343-
crate::intrinsics::codegen_intrinsic_call(fx, instance, args, destination, span);
343+
crate::intrinsics::codegen_intrinsic_call(
344+
fx,
345+
instance,
346+
args,
347+
destination,
348+
source_info,
349+
);
344350
return;
345351
}
346352
InstanceDef::DropGlue(_, None) => {
@@ -402,7 +408,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
402408

403409
// Pass the caller location for `#[track_caller]`.
404410
if instance.map(|inst| inst.def.requires_caller_location(fx.tcx)).unwrap_or(false) {
405-
let caller_location = fx.get_caller_location(span);
411+
let caller_location = fx.get_caller_location(source_info);
406412
args.push(CallArgument { value: caller_location, is_owned: false });
407413
}
408414

@@ -479,9 +485,10 @@ pub(crate) fn codegen_terminator_call<'tcx>(
479485
// FIXME find a cleaner way to support varargs
480486
if fn_sig.c_variadic {
481487
if !matches!(fn_sig.abi, Abi::C { .. }) {
482-
fx.tcx
483-
.sess
484-
.span_fatal(span, &format!("Variadic call for non-C abi {:?}", fn_sig.abi));
488+
fx.tcx.sess.span_fatal(
489+
source_info.span,
490+
&format!("Variadic call for non-C abi {:?}", fn_sig.abi),
491+
);
485492
}
486493
let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
487494
let abi_params = call_args
@@ -490,9 +497,10 @@ pub(crate) fn codegen_terminator_call<'tcx>(
490497
let ty = fx.bcx.func.dfg.value_type(arg);
491498
if !ty.is_int() {
492499
// FIXME set %al to upperbound on float args once floats are supported
493-
fx.tcx
494-
.sess
495-
.span_fatal(span, &format!("Non int ty {:?} for variadic call", ty));
500+
fx.tcx.sess.span_fatal(
501+
source_info.span,
502+
&format!("Non int ty {:?} for variadic call", ty),
503+
);
496504
}
497505
AbiParam::new(ty)
498506
})
@@ -513,7 +521,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
513521

514522
pub(crate) fn codegen_drop<'tcx>(
515523
fx: &mut FunctionCx<'_, '_, 'tcx>,
516-
span: Span,
524+
source_info: mir::SourceInfo,
517525
drop_place: CPlace<'tcx>,
518526
) {
519527
let ty = drop_place.layout().ty;
@@ -560,7 +568,7 @@ pub(crate) fn codegen_drop<'tcx>(
560568

561569
if drop_instance.def.requires_caller_location(fx.tcx) {
562570
// Pass the caller location for `#[track_caller]`.
563-
let caller_location = fx.get_caller_location(span);
571+
let caller_location = fx.get_caller_location(source_info);
564572
call_args.extend(
565573
adjust_arg_for_abi(fx, caller_location, &fn_abi.args[1], false).into_iter(),
566574
);

src/base.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
325325
AssertKind::BoundsCheck { ref len, ref index } => {
326326
let len = codegen_operand(fx, len).load_scalar(fx);
327327
let index = codegen_operand(fx, index).load_scalar(fx);
328-
let location = fx.get_caller_location(source_info.span).load_scalar(fx);
328+
let location = fx.get_caller_location(source_info).load_scalar(fx);
329329

330330
codegen_panic_inner(
331331
fx,
@@ -336,7 +336,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
336336
}
337337
_ => {
338338
let msg_str = msg.description();
339-
codegen_panic(fx, msg_str, source_info.span);
339+
codegen_panic(fx, msg_str, source_info);
340340
}
341341
}
342342
}
@@ -393,12 +393,12 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
393393
func,
394394
args,
395395
destination,
396-
fn_span,
396+
fn_span: _,
397397
cleanup: _,
398398
from_hir_call: _,
399399
} => {
400400
fx.tcx.sess.time("codegen call", || {
401-
crate::abi::codegen_terminator_call(fx, *fn_span, func, args, *destination)
401+
crate::abi::codegen_terminator_call(fx, source_info, func, args, *destination)
402402
});
403403
}
404404
TerminatorKind::InlineAsm {
@@ -450,7 +450,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
450450
}
451451
TerminatorKind::Drop { place, target, unwind: _ } => {
452452
let drop_place = codegen_place(fx, *place);
453-
crate::abi::codegen_drop(fx, source_info.span, drop_place);
453+
crate::abi::codegen_drop(fx, source_info, drop_place);
454454

455455
let target_block = fx.get_block(*target);
456456
fx.bcx.ins().jump(target_block, &[]);
@@ -898,14 +898,18 @@ pub(crate) fn codegen_operand<'tcx>(
898898
}
899899
}
900900

901-
pub(crate) fn codegen_panic<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, msg_str: &str, span: Span) {
902-
let location = fx.get_caller_location(span).load_scalar(fx);
901+
pub(crate) fn codegen_panic<'tcx>(
902+
fx: &mut FunctionCx<'_, '_, 'tcx>,
903+
msg_str: &str,
904+
source_info: mir::SourceInfo,
905+
) {
906+
let location = fx.get_caller_location(source_info).load_scalar(fx);
903907

904908
let msg_ptr = fx.anonymous_str(msg_str);
905909
let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
906910
let args = [msg_ptr, msg_len, location];
907911

908-
codegen_panic_inner(fx, rustc_hir::LangItem::Panic, &args, span);
912+
codegen_panic_inner(fx, rustc_hir::LangItem::Panic, &args, source_info.span);
909913
}
910914

911915
pub(crate) fn codegen_panic_inner<'tcx>(

src/common.rs

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -340,22 +340,46 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
340340
self.bcx.set_srcloc(SourceLoc::new(index as u32));
341341
}
342342

343-
pub(crate) fn get_caller_location(&mut self, span: Span) -> CValue<'tcx> {
344-
if let Some(loc) = self.caller_location {
345-
// `#[track_caller]` is used; return caller location instead of current location.
346-
return loc;
343+
// Note: must be kept in sync with get_caller_location from cg_ssa
344+
pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> {
345+
let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| {
346+
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
347+
let caller = fx.tcx.sess.source_map().lookup_char_pos(topmost.lo());
348+
let const_loc = fx.tcx.const_caller_location((
349+
rustc_span::symbol::Symbol::intern(
350+
&caller.file.name.prefer_remapped().to_string_lossy(),
351+
),
352+
caller.line as u32,
353+
caller.col_display as u32 + 1,
354+
));
355+
crate::constant::codegen_const_value(fx, const_loc, fx.tcx.caller_location_ty())
356+
};
357+
358+
// Walk up the `SourceScope`s, in case some of them are from MIR inlining.
359+
// If so, the starting `source_info.span` is in the innermost inlined
360+
// function, and will be replaced with outer callsite spans as long
361+
// as the inlined functions were `#[track_caller]`.
362+
loop {
363+
let scope_data = &self.mir.source_scopes[source_info.scope];
364+
365+
if let Some((callee, callsite_span)) = scope_data.inlined {
366+
// Stop inside the most nested non-`#[track_caller]` function,
367+
// before ever reaching its caller (which is irrelevant).
368+
if !callee.def.requires_caller_location(self.tcx) {
369+
return span_to_caller_location(self, source_info.span);
370+
}
371+
source_info.span = callsite_span;
372+
}
373+
374+
// Skip past all of the parents with `inlined: None`.
375+
match scope_data.inlined_parent_scope {
376+
Some(parent) => source_info.scope = parent,
377+
None => break,
378+
}
347379
}
348380

349-
let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
350-
let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
351-
let const_loc = self.tcx.const_caller_location((
352-
rustc_span::symbol::Symbol::intern(
353-
&caller.file.name.prefer_remapped().to_string_lossy(),
354-
),
355-
caller.line as u32,
356-
caller.col_display as u32 + 1,
357-
));
358-
crate::constant::codegen_const_value(self, const_loc, self.tcx.caller_location_ty())
381+
// No inlined `SourceScope`s, or all of them were `#[track_caller]`.
382+
self.caller_location.unwrap_or_else(|| span_to_caller_location(self, source_info.span))
359383
}
360384

361385
pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value {

0 commit comments

Comments
 (0)