2020-05-10 10:54:30 -04:00
|
|
|
use std::fmt::Write;
|
|
|
|
|
|
|
|
use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods};
|
2024-03-05 19:58:36 +01:00
|
|
|
use gccjit::{Struct, Type};
|
2020-05-10 10:54:30 -04:00
|
|
|
use rustc_middle::bug;
|
2023-08-28 18:21:16 +02:00
|
|
|
use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
|
2020-05-10 10:54:30 -04:00
|
|
|
use rustc_middle::ty::print::with_no_trimmed_paths;
|
2024-03-05 19:58:36 +01:00
|
|
|
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
|
2020-05-10 10:54:30 -04:00
|
|
|
use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
|
2024-03-05 19:58:36 +01:00
|
|
|
use rustc_target::abi::{
|
|
|
|
self, Abi, Align, FieldsShape, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface,
|
|
|
|
Variants, F128, F16, F32, F64,
|
|
|
|
};
|
2020-05-10 10:54:30 -04:00
|
|
|
|
2023-10-26 17:42:02 -04:00
|
|
|
use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
|
2020-05-10 10:54:30 -04:00
|
|
|
use crate::context::CodegenCx;
|
|
|
|
use crate::type_::struct_fields;
|
|
|
|
|
|
|
|
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
|
|
|
|
fn type_from_unsigned_integer(&self, i: Integer) -> Type<'gcc> {
|
|
|
|
use Integer::*;
|
|
|
|
match i {
|
|
|
|
I8 => self.type_u8(),
|
|
|
|
I16 => self.type_u16(),
|
|
|
|
I32 => self.type_u32(),
|
|
|
|
I64 => self.type_u64(),
|
|
|
|
I128 => self.type_u128(),
|
|
|
|
}
|
|
|
|
}
|
2022-06-06 22:04:37 -04:00
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
#[cfg(feature = "master")]
|
2022-06-06 22:04:37 -04:00
|
|
|
pub fn type_int_from_ty(&self, t: ty::IntTy) -> Type<'gcc> {
|
|
|
|
match t {
|
|
|
|
ty::IntTy::Isize => self.type_isize(),
|
|
|
|
ty::IntTy::I8 => self.type_i8(),
|
|
|
|
ty::IntTy::I16 => self.type_i16(),
|
|
|
|
ty::IntTy::I32 => self.type_i32(),
|
|
|
|
ty::IntTy::I64 => self.type_i64(),
|
|
|
|
ty::IntTy::I128 => self.type_i128(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
#[cfg(feature = "master")]
|
2022-06-06 22:04:37 -04:00
|
|
|
pub fn type_uint_from_ty(&self, t: ty::UintTy) -> Type<'gcc> {
|
|
|
|
match t {
|
|
|
|
ty::UintTy::Usize => self.type_isize(),
|
|
|
|
ty::UintTy::U8 => self.type_i8(),
|
|
|
|
ty::UintTy::U16 => self.type_i16(),
|
|
|
|
ty::UintTy::U32 => self.type_i32(),
|
|
|
|
ty::UintTy::U64 => self.type_i64(),
|
|
|
|
ty::UintTy::U128 => self.type_i128(),
|
|
|
|
}
|
|
|
|
}
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
|
|
|
|
2023-03-05 12:03:19 -05:00
|
|
|
impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
|
|
|
|
pub fn align_of(&self, ty: Ty<'tcx>) -> Align {
|
|
|
|
self.layout_of(ty).align.abi
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
fn uncached_gcc_type<'gcc, 'tcx>(
|
|
|
|
cx: &CodegenCx<'gcc, 'tcx>,
|
|
|
|
layout: TyAndLayout<'tcx>,
|
|
|
|
defer: &mut Option<(Struct<'gcc>, TyAndLayout<'tcx>)>,
|
|
|
|
) -> Type<'gcc> {
|
2020-05-10 10:54:30 -04:00
|
|
|
match layout.abi {
|
|
|
|
Abi::Scalar(_) => bug!("handled elsewhere"),
|
|
|
|
Abi::Vector { ref element, count } => {
|
|
|
|
let element = layout.scalar_gcc_type_at(cx, element, Size::ZERO);
|
2023-03-05 12:03:19 -05:00
|
|
|
let element =
|
|
|
|
// NOTE: gcc doesn't allow pointer types in vectors.
|
|
|
|
if element.get_pointee().is_some() {
|
|
|
|
cx.usize_type
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
element
|
|
|
|
};
|
2020-05-10 10:54:30 -04:00
|
|
|
return cx.context.new_vector_type(element, count);
|
2024-03-05 19:58:36 +01:00
|
|
|
}
|
2020-05-10 10:54:30 -04:00
|
|
|
Abi::ScalarPair(..) => {
|
|
|
|
return cx.type_struct(
|
|
|
|
&[
|
2023-08-28 18:21:16 +02:00
|
|
|
layout.scalar_pair_element_gcc_type(cx, 0),
|
|
|
|
layout.scalar_pair_element_gcc_type(cx, 1),
|
2020-05-10 10:54:30 -04:00
|
|
|
],
|
|
|
|
false,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
Abi::Uninhabited | Abi::Aggregate { .. } => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
let name = match layout.ty.kind() {
|
|
|
|
// FIXME(eddyb) producing readable type names for trait objects can result
|
|
|
|
// in problematically distinct types due to HRTB and subtyping (see #47638).
|
|
|
|
// ty::Dynamic(..) |
|
2024-03-05 19:58:36 +01:00
|
|
|
ty::Adt(..)
|
|
|
|
| ty::Closure(..)
|
|
|
|
| ty::CoroutineClosure(..)
|
|
|
|
| ty::Foreign(..)
|
|
|
|
| ty::Coroutine(..)
|
|
|
|
| ty::Str
|
2020-05-10 10:54:30 -04:00
|
|
|
if !cx.sess().fewer_names() =>
|
|
|
|
{
|
2022-02-16 13:04:48 -05:00
|
|
|
let mut name = with_no_trimmed_paths!(layout.ty.to_string());
|
2020-05-10 10:54:30 -04:00
|
|
|
if let (&ty::Adt(def, _), &Variants::Single { index }) =
|
|
|
|
(layout.ty.kind(), &layout.variants)
|
|
|
|
{
|
2022-03-05 07:28:41 +11:00
|
|
|
if def.is_enum() && !def.variants().is_empty() {
|
|
|
|
write!(&mut name, "::{}", def.variant(index).name).unwrap();
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
|
|
|
}
|
2023-12-21 01:52:10 +00:00
|
|
|
if let (&ty::Coroutine(_, _), &Variants::Single { index }) =
|
2020-05-10 10:54:30 -04:00
|
|
|
(layout.ty.kind(), &layout.variants)
|
|
|
|
{
|
2023-10-19 16:06:43 +00:00
|
|
|
write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap();
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
|
|
|
Some(name)
|
|
|
|
}
|
|
|
|
ty::Adt(..) => {
|
|
|
|
// If `Some` is returned then a named struct is created in LLVM. Name collisions are
|
|
|
|
// avoided by LLVM (with increasing suffixes). If rustc doesn't generate names then that
|
|
|
|
// can improve perf.
|
2021-08-15 08:28:46 -04:00
|
|
|
// FIXME(antoyo): I don't think that's true for libgccjit.
|
2020-05-10 10:54:30 -04:00
|
|
|
Some(String::new())
|
|
|
|
}
|
|
|
|
_ => None,
|
|
|
|
};
|
|
|
|
|
|
|
|
match layout.fields {
|
|
|
|
FieldsShape::Primitive | FieldsShape::Union(_) => {
|
|
|
|
let fill = cx.type_padding_filler(layout.size, layout.align.abi);
|
|
|
|
let packed = false;
|
|
|
|
match name {
|
|
|
|
None => cx.type_struct(&[fill], packed),
|
|
|
|
Some(ref name) => {
|
|
|
|
let gcc_type = cx.type_named_struct(name);
|
|
|
|
cx.set_struct_body(gcc_type, &[fill], packed);
|
|
|
|
gcc_type.as_type()
|
2024-03-05 19:58:36 +01:00
|
|
|
}
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
|
|
|
}
|
2023-03-05 12:03:19 -05:00
|
|
|
FieldsShape::Array { count, .. } => cx.type_array(layout.field(cx, 0).gcc_type(cx), count),
|
2024-03-05 19:58:36 +01:00
|
|
|
FieldsShape::Arbitrary { .. } => match name {
|
|
|
|
None => {
|
|
|
|
let (gcc_fields, packed) = struct_fields(cx, layout);
|
|
|
|
cx.type_struct(&gcc_fields, packed)
|
|
|
|
}
|
|
|
|
Some(ref name) => {
|
|
|
|
let gcc_type = cx.type_named_struct(name);
|
|
|
|
*defer = Some((gcc_type, layout));
|
|
|
|
gcc_type.as_type()
|
|
|
|
}
|
|
|
|
},
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait LayoutGccExt<'tcx> {
|
|
|
|
fn is_gcc_immediate(&self) -> bool;
|
|
|
|
fn is_gcc_scalar_pair(&self) -> bool;
|
2023-03-05 12:03:19 -05:00
|
|
|
fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
|
2020-05-10 10:54:30 -04:00
|
|
|
fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
|
2024-03-05 19:58:36 +01:00
|
|
|
fn scalar_gcc_type_at<'gcc>(
|
|
|
|
&self,
|
|
|
|
cx: &CodegenCx<'gcc, 'tcx>,
|
|
|
|
scalar: &abi::Scalar,
|
|
|
|
offset: Size,
|
|
|
|
) -> Type<'gcc>;
|
|
|
|
fn scalar_pair_element_gcc_type<'gcc>(
|
|
|
|
&self,
|
|
|
|
cx: &CodegenCx<'gcc, 'tcx>,
|
|
|
|
index: usize,
|
|
|
|
) -> Type<'gcc>;
|
|
|
|
fn pointee_info_at<'gcc>(
|
|
|
|
&self,
|
|
|
|
cx: &CodegenCx<'gcc, 'tcx>,
|
|
|
|
offset: Size,
|
|
|
|
) -> Option<PointeeInfo>;
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
|
|
|
|
fn is_gcc_immediate(&self) -> bool {
|
|
|
|
match self.abi {
|
|
|
|
Abi::Scalar(_) | Abi::Vector { .. } => true,
|
2023-05-07 03:00:41 -07:00
|
|
|
Abi::ScalarPair(..) | Abi::Uninhabited | Abi::Aggregate { .. } => false,
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_gcc_scalar_pair(&self) -> bool {
|
|
|
|
match self.abi {
|
|
|
|
Abi::ScalarPair(..) => true,
|
|
|
|
Abi::Uninhabited | Abi::Scalar(_) | Abi::Vector { .. } | Abi::Aggregate { .. } => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the GCC type corresponding to a Rust type, i.e., `rustc_middle::ty::Ty`.
|
|
|
|
/// The pointee type of the pointer in `PlaceRef` is always this type.
|
|
|
|
/// For sized types, it is also the right LLVM type for an `alloca`
|
|
|
|
/// containing a value of that type, and most immediates (except `bool`).
|
|
|
|
/// Unsized types, however, are represented by a "minimal unit", e.g.
|
|
|
|
/// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this
|
|
|
|
/// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.
|
|
|
|
/// If the type is an unsized struct, the regular layout is generated,
|
|
|
|
/// with the inner-most trailing unsized field using the "minimal unit"
|
|
|
|
/// of that field's type - this is useful for taking the address of
|
|
|
|
/// that field and ensuring the struct has the right alignment.
|
2023-03-05 12:03:19 -05:00
|
|
|
fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
|
2023-10-09 15:53:34 -04:00
|
|
|
use crate::rustc_middle::ty::layout::FnAbiOf;
|
2023-08-28 16:35:22 +02:00
|
|
|
// This must produce the same result for `repr(transparent)` wrappers as for the inner type!
|
|
|
|
// In other words, this should generally not look at the type at all, but only at the
|
|
|
|
// layout.
|
2020-05-10 10:54:30 -04:00
|
|
|
if let Abi::Scalar(ref scalar) = self.abi {
|
|
|
|
// Use a different cache for scalars because pointers to DSTs
|
|
|
|
// can be either fat or thin (data pointers of fat pointers).
|
|
|
|
if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) {
|
|
|
|
return ty;
|
|
|
|
}
|
2024-03-05 19:58:36 +01:00
|
|
|
let ty = match *self.ty.kind() {
|
|
|
|
// NOTE: we cannot remove this match like in the LLVM codegen because the call
|
|
|
|
// to fn_ptr_backend_type handle the on-stack attribute.
|
|
|
|
// TODO(antoyo): find a less hackish way to hande the on-stack attribute.
|
|
|
|
ty::FnPtr(sig) => {
|
|
|
|
cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty()))
|
|
|
|
}
|
|
|
|
_ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO),
|
|
|
|
};
|
2020-05-10 10:54:30 -04:00
|
|
|
cx.scalar_types.borrow_mut().insert(self.ty, ty);
|
|
|
|
return ty;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check the cache.
|
2024-03-05 19:58:36 +01:00
|
|
|
let variant_index = match self.variants {
|
|
|
|
Variants::Single { index } => Some(index),
|
|
|
|
_ => None,
|
|
|
|
};
|
2020-05-10 10:54:30 -04:00
|
|
|
let cached_type = cx.types.borrow().get(&(self.ty, variant_index)).cloned();
|
|
|
|
if let Some(ty) = cached_type {
|
|
|
|
return ty;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert!(!self.ty.has_escaping_bound_vars(), "{:?} has escaping bound vars", self.ty);
|
|
|
|
|
|
|
|
// Make sure lifetimes are erased, to avoid generating distinct LLVM
|
|
|
|
// types for Rust types that only differ in the choice of lifetimes.
|
|
|
|
let normal_ty = cx.tcx.erase_regions(self.ty);
|
|
|
|
|
|
|
|
let mut defer = None;
|
2024-03-05 19:58:36 +01:00
|
|
|
let ty = if self.ty != normal_ty {
|
|
|
|
let mut layout = cx.layout_of(normal_ty);
|
|
|
|
if let Some(v) = variant_index {
|
|
|
|
layout = layout.for_variant(cx, v);
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
2024-03-05 19:58:36 +01:00
|
|
|
layout.gcc_type(cx)
|
|
|
|
} else {
|
|
|
|
uncached_gcc_type(cx, *self, &mut defer)
|
|
|
|
};
|
2020-05-10 10:54:30 -04:00
|
|
|
|
|
|
|
cx.types.borrow_mut().insert((self.ty, variant_index), ty);
|
|
|
|
|
2023-03-05 12:03:19 -05:00
|
|
|
if let Some((deferred_ty, layout)) = defer {
|
2021-08-15 08:28:46 -04:00
|
|
|
let (fields, packed) = struct_fields(cx, layout);
|
2023-03-05 12:03:19 -05:00
|
|
|
cx.set_struct_body(deferred_ty, &fields, packed);
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
ty
|
|
|
|
}
|
|
|
|
|
|
|
|
fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
|
|
|
|
if let Abi::Scalar(ref scalar) = self.abi {
|
|
|
|
if scalar.is_bool() {
|
|
|
|
return cx.type_i1();
|
|
|
|
}
|
|
|
|
}
|
2023-03-05 12:03:19 -05:00
|
|
|
self.gcc_type(cx)
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
fn scalar_gcc_type_at<'gcc>(
|
|
|
|
&self,
|
|
|
|
cx: &CodegenCx<'gcc, 'tcx>,
|
|
|
|
scalar: &abi::Scalar,
|
|
|
|
offset: Size,
|
|
|
|
) -> Type<'gcc> {
|
2022-03-03 12:02:12 +00:00
|
|
|
match scalar.primitive() {
|
2020-05-10 10:54:30 -04:00
|
|
|
Int(i, true) => cx.type_from_integer(i),
|
|
|
|
Int(i, false) => cx.type_from_unsigned_integer(i),
|
2024-02-28 03:44:23 -05:00
|
|
|
F16 => cx.type_f16(),
|
2020-05-10 10:54:30 -04:00
|
|
|
F32 => cx.type_f32(),
|
|
|
|
F64 => cx.type_f64(),
|
2024-02-28 03:44:23 -05:00
|
|
|
F128 => cx.type_f128(),
|
2023-01-22 23:03:58 -05:00
|
|
|
Pointer(address_space) => {
|
2020-05-10 10:54:30 -04:00
|
|
|
// If we know the alignment, pick something better than i8.
|
2024-03-05 19:58:36 +01:00
|
|
|
let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) {
|
|
|
|
cx.type_pointee_for_align(pointee.align)
|
|
|
|
} else {
|
|
|
|
cx.type_i8()
|
|
|
|
};
|
2023-01-22 23:03:58 -05:00
|
|
|
cx.type_ptr_to_ext(pointee, address_space)
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
fn scalar_pair_element_gcc_type<'gcc>(
|
|
|
|
&self,
|
|
|
|
cx: &CodegenCx<'gcc, 'tcx>,
|
|
|
|
index: usize,
|
|
|
|
) -> Type<'gcc> {
|
2023-08-28 16:35:22 +02:00
|
|
|
// This must produce the same result for `repr(transparent)` wrappers as for the inner type!
|
|
|
|
// In other words, this should generally not look at the type at all, but only at the
|
|
|
|
// layout.
|
2020-05-10 10:54:30 -04:00
|
|
|
let (a, b) = match self.abi {
|
|
|
|
Abi::ScalarPair(ref a, ref b) => (a, b),
|
|
|
|
_ => bug!("TyAndLayout::scalar_pair_element_llty({:?}): not applicable", self),
|
|
|
|
};
|
|
|
|
let scalar = [a, b][index];
|
|
|
|
|
|
|
|
// Make sure to return the same type `immediate_gcc_type` would when
|
|
|
|
// dealing with an immediate pair. This means that `(bool, bool)` is
|
|
|
|
// effectively represented as `{i8, i8}` in memory and two `i1`s as an
|
|
|
|
// immediate, just like `bool` is typically `i8` in memory and only `i1`
|
|
|
|
// when immediate. We need to load/store `bool` as `i8` to avoid
|
|
|
|
// crippling LLVM optimizations or triggering other LLVM bugs with `i1`.
|
2021-08-15 08:28:46 -04:00
|
|
|
// TODO(antoyo): this bugs certainly don't happen in this case since the bool type is used instead of i1.
|
|
|
|
if scalar.is_bool() {
|
2020-05-10 10:54:30 -04:00
|
|
|
return cx.type_i1();
|
|
|
|
}
|
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
let offset = if index == 0 { Size::ZERO } else { a.size(cx).align_to(b.align(cx).abi) };
|
2020-05-10 10:54:30 -04:00
|
|
|
self.scalar_gcc_type_at(cx, scalar, offset)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn pointee_info_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>, offset: Size) -> Option<PointeeInfo> {
|
|
|
|
if let Some(&pointee) = cx.pointee_infos.borrow().get(&(self.ty, offset)) {
|
|
|
|
return pointee;
|
|
|
|
}
|
|
|
|
|
2023-07-21 22:35:57 -07:00
|
|
|
let result = Ty::ty_and_layout_pointee_info_at(*self, cx, offset);
|
2020-05-10 10:54:30 -04:00
|
|
|
|
|
|
|
cx.pointee_infos.borrow_mut().insert((self.ty, offset), result);
|
|
|
|
result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
|
|
|
|
fn backend_type(&self, layout: TyAndLayout<'tcx>) -> Type<'gcc> {
|
2023-03-05 12:03:19 -05:00
|
|
|
layout.gcc_type(self)
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> Type<'gcc> {
|
|
|
|
layout.immediate_gcc_type(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool {
|
|
|
|
layout.is_gcc_immediate()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool {
|
|
|
|
layout.is_gcc_scalar_pair()
|
|
|
|
}
|
|
|
|
|
2024-03-05 19:58:36 +01:00
|
|
|
fn scalar_pair_element_backend_type(
|
|
|
|
&self,
|
|
|
|
layout: TyAndLayout<'tcx>,
|
|
|
|
index: usize,
|
|
|
|
_immediate: bool,
|
|
|
|
) -> Type<'gcc> {
|
2023-08-28 18:21:16 +02:00
|
|
|
layout.scalar_pair_element_gcc_type(self, index)
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
fn cast_backend_type(&self, ty: &CastTarget) -> Type<'gcc> {
|
|
|
|
ty.gcc_type(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn fn_ptr_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
|
|
|
|
fn_abi.ptr_to_gcc_type(self)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn reg_backend_type(&self, _ty: &Reg) -> Type<'gcc> {
|
|
|
|
unimplemented!();
|
|
|
|
}
|
2021-08-14 10:05:49 -04:00
|
|
|
|
2023-06-19 18:51:02 -04:00
|
|
|
fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
|
2023-10-26 17:42:02 -04:00
|
|
|
// FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
|
2024-03-05 19:58:36 +01:00
|
|
|
let FnAbiGcc { return_type, arguments_type, is_c_variadic, .. } = fn_abi.gcc_type(self);
|
2023-10-26 17:42:02 -04:00
|
|
|
self.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic)
|
2021-08-14 10:05:49 -04:00
|
|
|
}
|
2020-05-10 10:54:30 -04:00
|
|
|
}
|