//! Conversion of internal Rust compiler `rustc_target` and `rustc_abi` items to stable ones. #![allow(rustc::usage_of_qualified_ty)] use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call}; use rustc_middle::ty; use rustc_public_bridge::Tables; use rustc_public_bridge::context::CompilerCtxt; use rustc_target::callconv; use crate::abi::{ AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength, IntegerType, Layout, LayoutShape, PassMode, Primitive, ReprFlags, ReprOptions, Scalar, TagEncoding, TyAndLayout, ValueAbi, VariantsShape, WrappingRange, }; use crate::compiler_interface::BridgeTys; use crate::target::MachineSize as Size; use crate::ty::{Align, VariantIdx}; use crate::unstable::Stable; use crate::{IndexedVal, opaque}; impl<'tcx> Stable<'tcx> for rustc_abi::VariantIdx { type T = VariantIdx; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { VariantIdx::to_val(self.as_usize()) } } impl<'tcx> Stable<'tcx> for rustc_abi::Endian { type T = crate::target::Endian; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { match self { rustc_abi::Endian::Little => crate::target::Endian::Little, rustc_abi::Endian::Big => crate::target::Endian::Big, } } } impl<'tcx> Stable<'tcx> for rustc_abi::TyAndLayout<'tcx, ty::Ty<'tcx>> { type T = TyAndLayout; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { TyAndLayout { ty: self.ty.stable(tables, cx), layout: self.layout.stable(tables, cx) } } } impl<'tcx> Stable<'tcx> for rustc_abi::Layout<'tcx> { type T = Layout; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { tables.layout_id(cx.lift(*self).unwrap()) } } impl<'tcx> Stable<'tcx> for rustc_abi::LayoutData { type T = LayoutShape; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { LayoutShape { fields: self.fields.stable(tables, cx), variants: self.variants.stable(tables, cx), abi: self.backend_repr.stable(tables, cx), abi_align: self.align.abi.stable(tables, cx), size: self.size.stable(tables, cx), } } } impl<'tcx> Stable<'tcx> for callconv::FnAbi<'tcx, ty::Ty<'tcx>> { type T = FnAbi; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { assert!(self.args.len() >= self.fixed_count as usize); assert!(!self.c_variadic || matches!(self.conv, CanonAbi::C)); FnAbi { args: self.args.as_ref().stable(tables, cx), ret: self.ret.stable(tables, cx), fixed_count: self.fixed_count, conv: self.conv.stable(tables, cx), c_variadic: self.c_variadic, } } } impl<'tcx> Stable<'tcx> for callconv::ArgAbi<'tcx, ty::Ty<'tcx>> { type T = ArgAbi; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { ArgAbi { ty: self.layout.ty.stable(tables, cx), layout: self.layout.layout.stable(tables, cx), mode: self.mode.stable(tables, cx), } } } impl<'tcx> Stable<'tcx> for CanonAbi { type T = CallConvention; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { match self { CanonAbi::C => CallConvention::C, CanonAbi::Rust => CallConvention::Rust, CanonAbi::RustCold => CallConvention::Cold, CanonAbi::Custom => CallConvention::Custom, CanonAbi::Arm(arm_call) => match arm_call { ArmCall::Aapcs => CallConvention::ArmAapcs, ArmCall::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall, ArmCall::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry, }, CanonAbi::GpuKernel => CallConvention::GpuKernel, CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind { InterruptKind::Avr => CallConvention::AvrInterrupt, InterruptKind::AvrNonBlocking => CallConvention::AvrNonBlockingInterrupt, InterruptKind::Msp430 => CallConvention::Msp430Intr, InterruptKind::RiscvMachine | InterruptKind::RiscvSupervisor => { CallConvention::RiscvInterrupt } InterruptKind::X86 => CallConvention::X86Intr, }, CanonAbi::X86(x86_call) => match x86_call { X86Call::Fastcall => CallConvention::X86Fastcall, X86Call::Stdcall => CallConvention::X86Stdcall, X86Call::SysV64 => CallConvention::X86_64SysV, X86Call::Thiscall => CallConvention::X86ThisCall, X86Call::Vectorcall => CallConvention::X86VectorCall, X86Call::Win64 => CallConvention::X86_64Win64, }, } } } impl<'tcx> Stable<'tcx> for callconv::PassMode { type T = PassMode; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { match self { callconv::PassMode::Ignore => PassMode::Ignore, callconv::PassMode::Direct(attr) => PassMode::Direct(opaque(attr)), callconv::PassMode::Pair(first, second) => { PassMode::Pair(opaque(first), opaque(second)) } callconv::PassMode::Cast { pad_i32, cast } => { PassMode::Cast { pad_i32: *pad_i32, cast: opaque(cast) } } callconv::PassMode::Indirect { attrs, meta_attrs, on_stack } => PassMode::Indirect { attrs: opaque(attrs), meta_attrs: opaque(meta_attrs), on_stack: *on_stack, }, } } } impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape { type T = FieldsShape; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { match self { rustc_abi::FieldsShape::Primitive => FieldsShape::Primitive, rustc_abi::FieldsShape::Union(count) => FieldsShape::Union(*count), rustc_abi::FieldsShape::Array { stride, count } => { FieldsShape::Array { stride: stride.stable(tables, cx), count: *count } } rustc_abi::FieldsShape::Arbitrary { offsets, .. } => { FieldsShape::Arbitrary { offsets: offsets.iter().as_slice().stable(tables, cx) } } } } } impl<'tcx> Stable<'tcx> for rustc_abi::Variants { type T = VariantsShape; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { match self { rustc_abi::Variants::Single { index } => { VariantsShape::Single { index: index.stable(tables, cx) } } rustc_abi::Variants::Empty => VariantsShape::Empty, rustc_abi::Variants::Multiple { tag, tag_encoding, tag_field, variants } => { VariantsShape::Multiple { tag: tag.stable(tables, cx), tag_encoding: tag_encoding.stable(tables, cx), tag_field: tag_field.stable(tables, cx), variants: variants.iter().as_slice().stable(tables, cx), } } } } } impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding { type T = TagEncoding; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { match self { rustc_abi::TagEncoding::Direct => TagEncoding::Direct, rustc_abi::TagEncoding::Niche { untagged_variant, niche_variants, niche_start } => { TagEncoding::Niche { untagged_variant: untagged_variant.stable(tables, cx), niche_variants: niche_variants.stable(tables, cx), niche_start: *niche_start, } } } } } impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr { type T = ValueAbi; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { match *self { rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables, cx)), rustc_abi::BackendRepr::ScalarPair(first, second) => { ValueAbi::ScalarPair(first.stable(tables, cx), second.stable(tables, cx)) } rustc_abi::BackendRepr::SimdVector { element, count } => { ValueAbi::Vector { element: element.stable(tables, cx), count } } rustc_abi::BackendRepr::Memory { sized } => ValueAbi::Aggregate { sized }, } } } impl<'tcx> Stable<'tcx> for rustc_abi::Size { type T = Size; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { Size::from_bits(self.bits_usize()) } } impl<'tcx> Stable<'tcx> for rustc_abi::Align { type T = Align; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { self.bytes() } } impl<'tcx> Stable<'tcx> for rustc_abi::Scalar { type T = Scalar; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { match self { rustc_abi::Scalar::Initialized { value, valid_range } => Scalar::Initialized { value: value.stable(tables, cx), valid_range: valid_range.stable(tables, cx), }, rustc_abi::Scalar::Union { value } => Scalar::Union { value: value.stable(tables, cx) }, } } } impl<'tcx> Stable<'tcx> for rustc_abi::Primitive { type T = Primitive; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { match self { rustc_abi::Primitive::Int(length, signed) => { Primitive::Int { length: length.stable(tables, cx), signed: *signed } } rustc_abi::Primitive::Float(length) => { Primitive::Float { length: length.stable(tables, cx) } } rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables, cx)), } } } impl<'tcx> Stable<'tcx> for rustc_abi::AddressSpace { type T = AddressSpace; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { AddressSpace(self.0) } } impl<'tcx> Stable<'tcx> for rustc_abi::Integer { type T = IntegerLength; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { match self { rustc_abi::Integer::I8 => IntegerLength::I8, rustc_abi::Integer::I16 => IntegerLength::I16, rustc_abi::Integer::I32 => IntegerLength::I32, rustc_abi::Integer::I64 => IntegerLength::I64, rustc_abi::Integer::I128 => IntegerLength::I128, } } } impl<'tcx> Stable<'tcx> for rustc_abi::Float { type T = FloatLength; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { match self { rustc_abi::Float::F16 => FloatLength::F16, rustc_abi::Float::F32 => FloatLength::F32, rustc_abi::Float::F64 => FloatLength::F64, rustc_abi::Float::F128 => FloatLength::F128, } } } impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange { type T = WrappingRange; fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { WrappingRange { start: self.start, end: self.end } } } impl<'tcx> Stable<'tcx> for rustc_abi::ReprFlags { type T = ReprFlags; fn stable<'cx>( &self, _tables: &mut Tables<'cx, BridgeTys>, _cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { ReprFlags { is_simd: self.intersects(Self::IS_SIMD), is_c: self.intersects(Self::IS_C), is_transparent: self.intersects(Self::IS_TRANSPARENT), is_linear: self.intersects(Self::IS_LINEAR), } } } impl<'tcx> Stable<'tcx> for rustc_abi::IntegerType { type T = IntegerType; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { match self { rustc_abi::IntegerType::Pointer(signed) => IntegerType::Pointer { is_signed: *signed }, rustc_abi::IntegerType::Fixed(integer, signed) => { IntegerType::Fixed { length: integer.stable(tables, cx), is_signed: *signed } } } } } impl<'tcx> Stable<'tcx> for rustc_abi::ReprOptions { type T = ReprOptions; fn stable<'cx>( &self, tables: &mut Tables<'cx, BridgeTys>, cx: &CompilerCtxt<'cx, BridgeTys>, ) -> Self::T { ReprOptions { int: self.int.map(|int| int.stable(tables, cx)), align: self.align.map(|align| align.stable(tables, cx)), pack: self.pack.map(|pack| pack.stable(tables, cx)), flags: self.flags.stable(tables, cx), } } }