+use cranelift_codegen::isa::TargetFrontendConfig;
use rustc_index::vec::IndexVec;
+use rustc_middle::ty::layout::{
+ FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers,
+};
use rustc_middle::ty::SymbolName;
use rustc_target::abi::call::FnAbi;
use rustc_target::abi::{Integer, Primitive};
}
pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type {
- match scalar.value {
+ match scalar.primitive() {
Primitive::Int(int, _sign) => match int {
Integer::I8 => types::I8,
Integer::I16 => types::I16,
},
ty::FnPtr(_) => pointer_ty(tcx),
ty::RawPtr(TypeAndMut { ty: pointee_ty, mutbl: _ }) | ty::Ref(_, pointee_ty, _) => {
- if has_ptr_meta(tcx, pointee_ty) {
+ if has_ptr_meta(tcx, *pointee_ty) {
return None;
} else {
pointer_ty(tcx)
}
}
- ty::Adt(adt_def, _) if adt_def.repr.simd() => {
+ ty::Adt(adt_def, _) if adt_def.repr().simd() => {
let (element, count) = match &tcx.layout_of(ParamEnv::reveal_all().and(ty)).unwrap().abi
{
Abi::Vector { element, count } => (element.clone(), *count),
_ => unreachable!(),
};
- match scalar_to_clif_type(tcx, element).by(u16::try_from(count).unwrap()) {
+ match scalar_to_clif_type(tcx, element).by(u32::try_from(count).unwrap()) {
// Cranelift currently only implements icmp for 128bit vectors.
Some(vector_ty) if vector_ty.bits() == 128 => vector_ty,
_ => return None,
ty: Ty<'tcx>,
) -> Option<(types::Type, types::Type)> {
Some(match ty.kind() {
- ty::Tuple(substs) if substs.len() == 2 => {
- let mut types = substs.types();
- let a = clif_type_from_ty(tcx, types.next().unwrap())?;
- let b = clif_type_from_ty(tcx, types.next().unwrap())?;
+ ty::Tuple(types) if types.len() == 2 => {
+ let a = clif_type_from_ty(tcx, types[0])?;
+ let b = clif_type_from_ty(tcx, types[1])?;
if a.is_vector() || b.is_vector() {
return None;
}
(a, b)
}
ty::RawPtr(TypeAndMut { ty: pointee_ty, mutbl: _ }) | ty::Ref(_, pointee_ty, _) => {
- if has_ptr_meta(tcx, pointee_ty) {
+ if has_ptr_meta(tcx, *pointee_ty) {
(pointer_ty(tcx), pointer_ty(tcx))
} else {
return None;
}
}
-pub(crate) struct FunctionCx<'m, 'clif, 'tcx> {
- pub(crate) cx: &'clif mut crate::CodegenCx<'m, 'tcx>,
+pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
+ pub(crate) cx: &'clif mut crate::CodegenCx<'tcx>,
+ pub(crate) module: &'m mut dyn Module,
pub(crate) tcx: TyCtxt<'tcx>,
- pub(crate) pointer_type: Type, // Cached from module
- pub(crate) vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
+ pub(crate) target_config: TargetFrontendConfig, // Cached from module
+ pub(crate) pointer_type: Type, // Cached from module
pub(crate) constants_cx: ConstantCx,
pub(crate) instance: Instance<'tcx>,
pub(crate) symbol_name: SymbolName<'tcx>,
pub(crate) mir: &'tcx Body<'tcx>,
- pub(crate) fn_abi: Option<FnAbi<'tcx, Ty<'tcx>>>,
+ pub(crate) fn_abi: Option<&'tcx FnAbi<'tcx, Ty<'tcx>>>,
pub(crate) bcx: FunctionBuilder<'clif>,
pub(crate) block_map: IndexVec<BasicBlock, Block>,
/// This should only be accessed by `CPlace::new_var`.
pub(crate) next_ssa_var: u32,
-
- pub(crate) inline_asm_index: u32,
}
-impl<'tcx> LayoutOf for FunctionCx<'_, '_, 'tcx> {
- type Ty = Ty<'tcx>;
- type TyAndLayout = TyAndLayout<'tcx>;
+impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
+ type LayoutOfResult = TyAndLayout<'tcx>;
- fn layout_of(&self, ty: Ty<'tcx>) -> TyAndLayout<'tcx> {
- RevealAllLayoutCx(self.tcx).layout_of(ty)
+ #[inline]
+ fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+ RevealAllLayoutCx(self.tcx).handle_layout_err(err, span, ty)
+ }
+}
+
+impl<'tcx> FnAbiOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
+ type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
+
+ #[inline]
+ fn handle_fn_abi_err(
+ &self,
+ err: FnAbiError<'tcx>,
+ span: Span,
+ fn_abi_request: FnAbiRequest<'tcx>,
+ ) -> ! {
+ RevealAllLayoutCx(self.tcx).handle_fn_abi_err(err, span, fn_abi_request)
}
}
self.bcx.set_srcloc(SourceLoc::new(index as u32));
}
- pub(crate) fn get_caller_location(&mut self, span: Span) -> CValue<'tcx> {
- if let Some(loc) = self.caller_location {
- // `#[track_caller]` is used; return caller location instead of current location.
- return loc;
- }
+ // Note: must be kept in sync with get_caller_location from cg_ssa
+ pub(crate) fn get_caller_location(&mut self, mut source_info: mir::SourceInfo) -> CValue<'tcx> {
+ let span_to_caller_location = |fx: &mut FunctionCx<'_, '_, 'tcx>, span: Span| {
+ let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
+ let caller = fx.tcx.sess.source_map().lookup_char_pos(topmost.lo());
+ let const_loc = fx.tcx.const_caller_location((
+ rustc_span::symbol::Symbol::intern(
+ &caller.file.name.prefer_remapped().to_string_lossy(),
+ ),
+ caller.line as u32,
+ caller.col_display as u32 + 1,
+ ));
+ crate::constant::codegen_const_value(fx, const_loc, fx.tcx.caller_location_ty())
+ };
+
+ // Walk up the `SourceScope`s, in case some of them are from MIR inlining.
+ // If so, the starting `source_info.span` is in the innermost inlined
+ // function, and will be replaced with outer callsite spans as long
+ // as the inlined functions were `#[track_caller]`.
+ loop {
+ let scope_data = &self.mir.source_scopes[source_info.scope];
+
+ if let Some((callee, callsite_span)) = scope_data.inlined {
+ // Stop inside the most nested non-`#[track_caller]` function,
+ // before ever reaching its caller (which is irrelevant).
+ if !callee.def.requires_caller_location(self.tcx) {
+ return span_to_caller_location(self, source_info.span);
+ }
+ source_info.span = callsite_span;
+ }
- let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
- let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
- let const_loc = self.tcx.const_caller_location((
- rustc_span::symbol::Symbol::intern(&caller.file.name.to_string()),
- caller.line as u32,
- caller.col_display as u32 + 1,
- ));
- crate::constant::codegen_const_value(self, const_loc, self.tcx.caller_location_ty())
- }
+ // Skip past all of the parents with `inlined: None`.
+ match scope_data.inlined_parent_scope {
+ Some(parent) => source_info.scope = parent,
+ None => break,
+ }
+ }
- pub(crate) fn triple(&self) -> &target_lexicon::Triple {
- self.cx.module.isa().triple()
+ // No inlined `SourceScope`s, or all of them were `#[track_caller]`.
+ self.caller_location.unwrap_or_else(|| span_to_caller_location(self, source_info.span))
}
- pub(crate) fn anonymous_str(&mut self, prefix: &str, msg: &str) -> Value {
- use std::collections::hash_map::DefaultHasher;
- use std::hash::{Hash, Hasher};
-
- let mut hasher = DefaultHasher::new();
- msg.hash(&mut hasher);
- let msg_hash = hasher.finish();
+ pub(crate) fn anonymous_str(&mut self, msg: &str) -> Value {
let mut data_ctx = DataContext::new();
data_ctx.define(msg.as_bytes().to_vec().into_boxed_slice());
- let msg_id = self
- .cx
- .module
- .declare_data(&format!("__{}_{:08x}", prefix, msg_hash), Linkage::Local, false, false)
- .unwrap();
+ let msg_id = self.module.declare_anonymous_data(false, false).unwrap();
// Ignore DuplicateDefinition error, as the data will be the same
- let _ = self.cx.module.define_data(msg_id, &data_ctx);
+ let _ = self.module.define_data(msg_id, &data_ctx);
- let local_msg_id = self.cx.module.declare_data_in_func(msg_id, self.bcx.func);
+ let local_msg_id = self.module.declare_data_in_func(msg_id, self.bcx.func);
if self.clif_comments.enabled() {
self.add_comment(local_msg_id, msg);
}
pub(crate) struct RevealAllLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>);
-impl<'tcx> LayoutOf for RevealAllLayoutCx<'tcx> {
- type Ty = Ty<'tcx>;
- type TyAndLayout = TyAndLayout<'tcx>;
+impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
+ type LayoutOfResult = TyAndLayout<'tcx>;
- fn layout_of(&self, ty: Ty<'tcx>) -> TyAndLayout<'tcx> {
- assert!(!ty.still_further_specializable());
- self.0.layout_of(ParamEnv::reveal_all().and(&ty)).unwrap_or_else(|e| {
- if let layout::LayoutError::SizeOverflow(_) = e {
- self.0.sess.fatal(&e.to_string())
- } else {
- bug!("failed to get layout for `{}`: {}", ty, e)
+ #[inline]
+ fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
+ if let layout::LayoutError::SizeOverflow(_) = err {
+ self.0.sess.span_fatal(span, &err.to_string())
+ } else {
+ span_bug!(span, "failed to get layout for `{}`: {}", ty, err)
+ }
+ }
+}
+
+impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
+ type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
+
+ #[inline]
+ fn handle_fn_abi_err(
+ &self,
+ err: FnAbiError<'tcx>,
+ span: Span,
+ fn_abi_request: FnAbiRequest<'tcx>,
+ ) -> ! {
+ if let FnAbiError::Layout(LayoutError::SizeOverflow(_)) = err {
+ self.0.sess.span_fatal(span, &err.to_string())
+ } else {
+ match fn_abi_request {
+ FnAbiRequest::OfFnPtr { sig, extra_args } => {
+ span_bug!(
+ span,
+ "`fn_abi_of_fn_ptr({}, {:?})` failed: {}",
+ sig,
+ extra_args,
+ err
+ );
+ }
+ FnAbiRequest::OfInstance { instance, extra_args } => {
+ span_bug!(
+ span,
+ "`fn_abi_of_instance({}, {:?})` failed: {}",
+ instance,
+ extra_args,
+ err
+ );
+ }
}
- })
+ }
}
}