|  | 
| 1 |  | -use rustc_abi::ExternAbi; | 
|  | 1 | +use rustc_abi::{BackendRepr, ExternAbi, Float, Integer, Primitive, Scalar}; | 
| 2 | 2 | use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err}; | 
| 3 | 3 | use rustc_hir::{self as hir, HirId}; | 
| 4 | 4 | use rustc_middle::bug; | 
| 5 |  | -use rustc_middle::ty::layout::LayoutError; | 
|  | 5 | +use rustc_middle::ty::layout::{LayoutError, TyAndLayout}; | 
| 6 | 6 | use rustc_middle::ty::{self, TyCtxt}; | 
| 7 | 7 | 
 | 
| 8 | 8 | use crate::errors; | 
| @@ -164,44 +164,34 @@ fn is_valid_cmse_output<'tcx>( | 
| 164 | 164 | ) -> Result<bool, &'tcx LayoutError<'tcx>> { | 
| 165 | 165 |     // this type is only used for layout computation, which does not rely on regions | 
| 166 | 166 |     let fn_sig = tcx.instantiate_bound_regions_with_erased(fn_sig); | 
|  | 167 | +    let fn_sig = tcx.erase_and_anonymize_regions(fn_sig); | 
| 167 | 168 | 
 | 
| 168 | 169 |     let typing_env = ty::TypingEnv::fully_monomorphized(); | 
|  | 170 | +    let layout = tcx.layout_of(typing_env.as_query_input(fn_sig.output()))?; | 
|  | 171 | + | 
|  | 172 | +    Ok(is_valid_cmse_output_layout(layout)) | 
|  | 173 | +} | 
| 169 | 174 | 
 | 
| 170 |  | -    let mut ret_ty = fn_sig.output(); | 
| 171 |  | -    let layout = tcx.layout_of(typing_env.as_query_input(ret_ty))?; | 
|  | 175 | +/// Returns whether the output will fit into the available registers | 
|  | 176 | +fn is_valid_cmse_output_layout<'tcx>(layout: TyAndLayout<'tcx>) -> bool { | 
| 172 | 177 |     let size = layout.layout.size().bytes(); | 
| 173 | 178 | 
 | 
| 174 | 179 |     if size <= 4 { | 
| 175 |  | -        return Ok(true); | 
|  | 180 | +        return true; | 
| 176 | 181 |     } else if size > 8 { | 
| 177 |  | -        return Ok(false); | 
|  | 182 | +        return false; | 
| 178 | 183 |     } | 
| 179 | 184 | 
 | 
| 180 |  | -    // next we need to peel any repr(transparent) layers off | 
| 181 |  | -    'outer: loop { | 
| 182 |  | -        let ty::Adt(adt_def, args) = ret_ty.kind() else { | 
| 183 |  | -            break; | 
| 184 |  | -        }; | 
| 185 |  | - | 
| 186 |  | -        if !adt_def.repr().transparent() { | 
| 187 |  | -            break; | 
| 188 |  | -        } | 
|  | 185 | +    // Accept scalar 64-bit types. | 
|  | 186 | +    let BackendRepr::Scalar(scalar) = layout.layout.backend_repr else { | 
|  | 187 | +        return false; | 
|  | 188 | +    }; | 
| 189 | 189 | 
 | 
| 190 |  | -        // the first field with non-trivial size and alignment must be the data | 
| 191 |  | -        for variant_def in adt_def.variants() { | 
| 192 |  | -            for field_def in variant_def.fields.iter() { | 
| 193 |  | -                let ty = field_def.ty(tcx, args); | 
| 194 |  | -                let layout = tcx.layout_of(typing_env.as_query_input(ty))?; | 
| 195 |  | - | 
| 196 |  | -                if !layout.layout.is_1zst() { | 
| 197 |  | -                    ret_ty = ty; | 
| 198 |  | -                    continue 'outer; | 
| 199 |  | -                } | 
| 200 |  | -            } | 
| 201 |  | -        } | 
| 202 |  | -    } | 
|  | 190 | +    let Scalar::Initialized { value, .. } = scalar else { | 
|  | 191 | +        return false; | 
|  | 192 | +    }; | 
| 203 | 193 | 
 | 
| 204 |  | -    Ok(ret_ty == tcx.types.i64 || ret_ty == tcx.types.u64 || ret_ty == tcx.types.f64) | 
|  | 194 | +    matches!(value, Primitive::Int(Integer::I64, _) | Primitive::Float(Float::F64)) | 
| 205 | 195 | } | 
| 206 | 196 | 
 | 
| 207 | 197 | fn should_emit_generic_error<'tcx>(abi: ExternAbi, layout_err: &'tcx LayoutError<'tcx>) -> bool { | 
|  | 
0 commit comments