blob: 782e75a930e071eee96a8f514b4f99e056665cbe [file] [log] [blame]
//! 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<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
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<rustc_abi::FieldIdx> {
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<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
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<rustc_abi::VariantIdx> {
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),
}
}
}