1
Fork 0

Add monomorphization errors

This commit is contained in:
Ellis Hoag 2022-09-11 16:43:18 -07:00 committed by Antoni Boucher
parent f21041d7c3
commit ef3aaa1f21
3 changed files with 271 additions and 147 deletions

View file

@ -1,6 +1,7 @@
use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_macros::SessionDiagnostic; use rustc_macros::SessionDiagnostic;
use rustc_span::Span; use rustc_middle::ty::Ty;
use rustc_span::{Span, Symbol};
use std::borrow::Cow; use std::borrow::Cow;
struct ExitCode { struct ExitCode {
@ -29,6 +30,201 @@ impl RanlibFailure {
} }
} }
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_basic_integer, code = "E0511")]
pub(crate) struct InvalidMonomorphizationBasicInteger<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub ty: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_invalid_float_vector, code = "E0511")]
pub(crate) struct InvalidMonomorphizationInvalidFloatVector<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub elem_ty: &'a str,
pub vec_ty: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_not_float, code = "E0511")]
pub(crate) struct InvalidMonomorphizationNotFloat<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub ty: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_unrecognized, code = "E0511")]
pub(crate) struct InvalidMonomorphizationUnrecognized {
#[primary_span]
pub span: Span,
pub name: Symbol,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_expected_signed_unsigned, code = "E0511")]
pub(crate) struct InvalidMonomorphizationExpectedSignedUnsigned<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub elem_ty: Ty<'a>,
pub vec_ty: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_unsupported_element, code = "E0511")]
pub(crate) struct InvalidMonomorphizationUnsupportedElement<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_ty: Ty<'a>,
pub elem_ty: Ty<'a>,
pub ret_ty: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_invalid_bitmask, code = "E0511")]
pub(crate) struct InvalidMonomorphizationInvalidBitmask<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub ty: Ty<'a>,
pub expected_int_bits: u64,
pub expected_bytes: u64,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_simd_shuffle, code = "E0511")]
pub(crate) struct InvalidMonomorphizationSimdShuffle<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub ty: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_expected_simd, code = "E0511")]
pub(crate) struct InvalidMonomorphizationExpectedSimd<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub position: &'a str,
pub found_ty: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_mask_type, code = "E0511")]
pub(crate) struct InvalidMonomorphizationMaskType<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub ty: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_return_length, code = "E0511")]
pub(crate) struct InvalidMonomorphizationReturnLength<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_len: u64,
pub ret_ty: Ty<'a>,
pub out_len: u64,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_return_length_input_type, code = "E0511")]
pub(crate) struct InvalidMonomorphizationReturnLengthInputType<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_len: u64,
pub in_ty: Ty<'a>,
pub ret_ty: Ty<'a>,
pub out_len: u64,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_return_element, code = "E0511")]
pub(crate) struct InvalidMonomorphizationReturnElement<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_elem: Ty<'a>,
pub in_ty: Ty<'a>,
pub ret_ty: Ty<'a>,
pub out_ty: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_return_type, code = "E0511")]
pub(crate) struct InvalidMonomorphizationReturnType<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_elem: Ty<'a>,
pub in_ty: Ty<'a>,
pub ret_ty: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_inserted_type, code = "E0511")]
pub(crate) struct InvalidMonomorphizationInsertedType<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_elem: Ty<'a>,
pub in_ty: Ty<'a>,
pub out_ty: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_return_integer_type, code = "E0511")]
pub(crate) struct InvalidMonomorphizationReturnIntegerType<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub ret_ty: Ty<'a>,
pub out_ty: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_mismatched_lengths, code = "E0511")]
pub(crate) struct InvalidMonomorphizationMismatchedLengths {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub m_len: u64,
pub v_len: u64,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_unsupported_cast, code = "E0511")]
pub(crate) struct InvalidMonomorphizationUnsupportedCast<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_ty: Ty<'a>,
pub in_elem: Ty<'a>,
pub ret_ty: Ty<'a>,
pub out_elem: Ty<'a>,
}
#[derive(SessionDiagnostic)]
#[diag(codegen_gcc::invalid_monomorphization_unsupported_operation, code = "E0511")]
pub(crate) struct InvalidMonomorphizationUnsupportedOperation<'a> {
#[primary_span]
pub span: Span,
pub name: Symbol,
pub in_ty: Ty<'a>,
pub in_elem: Ty<'a>,
}
#[derive(SessionDiagnostic)] #[derive(SessionDiagnostic)]
#[diag(codegen_gcc::layout_size_overflow)] #[diag(codegen_gcc::layout_size_overflow)]
pub(crate) struct LayoutSizeOverflow { pub(crate) struct LayoutSizeOverflow {

View file

@ -7,7 +7,7 @@ use std::iter;
use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType}; use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp, FunctionType};
use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::MemFlags;
use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::base::wants_msvc_seh;
use rustc_codegen_ssa::common::{IntPredicate, span_invalid_monomorphization_error}; use rustc_codegen_ssa::common::IntPredicate;
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods}; use rustc_codegen_ssa::traits::{ArgAbiMethods, BaseTypeMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods};
@ -31,6 +31,7 @@ use crate::abi::FnAbiGccExt;
use crate::builder::Builder; use crate::builder::Builder;
use crate::common::{SignType, TypeReflection}; use crate::common::{SignType, TypeReflection};
use crate::context::CodegenCx; use crate::context::CodegenCx;
use crate::errors::InvalidMonomorphizationBasicInteger;
use crate::type_of::LayoutGccExt; use crate::type_of::LayoutGccExt;
use crate::intrinsic::simd::generic_simd_intrinsic; use crate::intrinsic::simd::generic_simd_intrinsic;
@ -253,15 +254,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
_ => bug!(), _ => bug!(),
}, },
None => { None => {
span_invalid_monomorphization_error( tcx.sess.emit_err(InvalidMonomorphizationBasicInteger { span, name, ty });
tcx.sess,
span,
&format!(
"invalid monomorphization of `{}` intrinsic: \
expected basic integer type, found `{}`",
name, ty
),
);
return; return;
} }
} }

View file

@ -2,7 +2,7 @@
use gccjit::{ToRValue, ComparisonOp, UnaryOp}; use gccjit::{ToRValue, ComparisonOp, UnaryOp};
use gccjit::{BinaryOp, RValue, Type}; use gccjit::{BinaryOp, RValue, Type};
use rustc_codegen_ssa::base::compare_simd_types; use rustc_codegen_ssa::base::compare_simd_types;
use rustc_codegen_ssa::common::{IntPredicate, TypeKind, span_invalid_monomorphization_error}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::operand::OperandRef;
use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods}; use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods};
@ -16,42 +16,46 @@ use rustc_target::abi::Align;
use crate::builder::Builder; use crate::builder::Builder;
#[cfg(feature="master")] #[cfg(feature="master")]
use crate::context::CodegenCx; use crate::context::CodegenCx;
use crate::errors::{
InvalidMonomorphizationInvalidFloatVector,
InvalidMonomorphizationNotFloat,
InvalidMonomorphizationUnrecognized,
InvalidMonomorphizationExpectedSignedUnsigned,
InvalidMonomorphizationUnsupportedElement,
InvalidMonomorphizationInvalidBitmask,
InvalidMonomorphizationSimdShuffle,
InvalidMonomorphizationExpectedSimd,
InvalidMonomorphizationMaskType,
InvalidMonomorphizationReturnLength,
InvalidMonomorphizationReturnLengthInputType,
InvalidMonomorphizationReturnElement,
InvalidMonomorphizationReturnType,
InvalidMonomorphizationInsertedType,
InvalidMonomorphizationReturnIntegerType,
InvalidMonomorphizationMismatchedLengths,
InvalidMonomorphizationUnsupportedOperation
};
pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, args: &[OperandRef<'tcx, RValue<'gcc>>], ret_ty: Ty<'tcx>, llret_ty: Type<'gcc>, span: Span) -> Result<RValue<'gcc>, ()> { pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, name: Symbol, callee_ty: Ty<'tcx>, args: &[OperandRef<'tcx, RValue<'gcc>>], ret_ty: Ty<'tcx>, llret_ty: Type<'gcc>, span: Span) -> Result<RValue<'gcc>, ()> {
// macros for error handling: // macros for error handling:
#[allow(unused_macro_rules)]
macro_rules! emit_error {
($msg: tt) => {
emit_error!($msg, )
};
($msg: tt, $($fmt: tt)*) => {
span_invalid_monomorphization_error(
bx.sess(), span,
&format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
name, $($fmt)*));
}
}
macro_rules! return_error { macro_rules! return_error {
($($fmt: tt)*) => { ($err:expr) => {
{ {
emit_error!($($fmt)*); bx.sess().emit_err($err);
return Err(()); return Err(());
} }
} }
} }
macro_rules! require { macro_rules! require {
($cond: expr, $($fmt: tt)*) => { ($cond:expr, $err:expr) => {
if !$cond { if !$cond {
return_error!($($fmt)*); return_error!($err);
} }
}; }
} }
macro_rules! require_simd { macro_rules! require_simd {
($ty: expr, $position: expr) => { ($ty: expr, $position: expr) => {
require!($ty.is_simd(), "expected SIMD {} type, found non-SIMD `{}`", $position, $ty) require!($ty.is_simd(), InvalidMonomorphizationExpectedSimd { span, name, position: $position, found_ty: $ty })
}; };
} }
@ -83,10 +87,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
bx.load(int_ty, ptr, Align::ONE) bx.load(int_ty, ptr, Align::ONE)
} }
_ => return_error!( _ => return_error!(
"invalid bitmask `{}`, expected `u{}` or `[u8; {}]`", InvalidMonomorphizationInvalidBitmask { span, name, ty: mask_ty, expected_int_bits, expected_bytes }
mask_ty,
expected_int_bits,
expected_bytes
), ),
}; };
@ -133,18 +134,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
require!( require!(
in_len == out_len, in_len == out_len,
"expected return type with length {} (same as input type `{}`), \ InvalidMonomorphizationReturnLengthInputType { span, name, in_len, in_ty, ret_ty, out_len }
found `{}` with length {}",
in_len,
in_ty,
ret_ty,
out_len
); );
require!( require!(
bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer, bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
"expected return type with integer elements, found `{}` with non-integer `{}`", InvalidMonomorphizationReturnIntegerType {span, name, ret_ty, out_ty}
ret_ty,
out_ty
); );
return Ok(compare_simd_types( return Ok(compare_simd_types(
@ -169,8 +163,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
}) })
} }
_ => return_error!( _ => return_error!(
"simd_shuffle index must be an array of `u32`, got `{}`", InvalidMonomorphizationSimdShuffle { span, name, ty: args[2].layout.ty }
args[2].layout.ty
), ),
} }
} }
@ -185,19 +178,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx()); let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
require!( require!(
out_len == n, out_len == n,
"expected return type of length {}, found `{}` with length {}", InvalidMonomorphizationReturnLength { span, name, in_len: n, ret_ty, out_len }
n,
ret_ty,
out_len
); );
require!( require!(
in_elem == out_ty, in_elem == out_ty,
"expected return element type `{}` (element of input `{}`), \ InvalidMonomorphizationReturnElement { span, name, in_elem, in_ty, ret_ty, out_ty }
found `{}` with element type `{}`",
in_elem,
in_ty,
ret_ty,
out_ty
); );
let vector = args[2].immediate(); let vector = args[2].immediate();
@ -213,10 +198,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
if name == sym::simd_insert { if name == sym::simd_insert {
require!( require!(
in_elem == arg_tys[2], in_elem == arg_tys[2],
"expected inserted type `{}` (element of input `{}`), found `{}`", InvalidMonomorphizationInsertedType { span, name, in_elem, in_ty, out_ty: arg_tys[2] }
in_elem,
in_ty,
arg_tys[2]
); );
let vector = args[0].immediate(); let vector = args[0].immediate();
let index = args[1].immediate(); let index = args[1].immediate();
@ -233,10 +215,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
if name == sym::simd_extract { if name == sym::simd_extract {
require!( require!(
ret_ty == in_elem, ret_ty == in_elem,
"expected return type `{}` (element of input `{}`), found `{}`", InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
in_elem,
in_ty,
ret_ty
); );
let vector = args[0].immediate(); let vector = args[0].immediate();
return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue()); return Ok(bx.context.new_vector_access(None, vector, args[1].immediate()).to_rvalue());
@ -249,13 +228,11 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx()); let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
require!( require!(
m_len == v_len, m_len == v_len,
"mismatched lengths: mask length `{}` != other vector length `{}`", InvalidMonomorphizationMismatchedLengths { span, name, m_len, v_len }
m_len,
v_len
); );
match m_elem_ty.kind() { match m_elem_ty.kind() {
ty::Int(_) => {} ty::Int(_) => {}
_ => return_error!("mask element type is `{}`, expected `i_`", m_elem_ty), _ => return_error!(InvalidMonomorphizationMaskType { span, name, ty: m_elem_ty }),
} }
return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate())); return Ok(bx.vector_select(args[0].immediate(), args[1].immediate(), args[2].immediate()));
} }
@ -266,12 +243,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx()); let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
require!( require!(
in_len == out_len, in_len == out_len,
"expected return type with length {} (same as input type `{}`), \ InvalidMonomorphizationReturnLengthInputType { span, name, in_len, in_ty, ret_ty, out_len }
found `{}` with length {}",
in_len,
in_ty,
ret_ty,
out_len
); );
// casting cares about nominal type, not just structural type // casting cares about nominal type, not just structural type
if in_elem == out_elem { if in_elem == out_elem {
@ -322,10 +294,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
})* })*
_ => {}, _ => {},
} }
require!(false, return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem })
"unsupported operation on `{}` with element `{}`",
in_ty,
in_elem)
})* })*
} }
} }
@ -403,23 +372,14 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
span: Span, span: Span,
args: &[OperandRef<'tcx, RValue<'gcc>>], args: &[OperandRef<'tcx, RValue<'gcc>>],
) -> Result<RValue<'gcc>, ()> { ) -> Result<RValue<'gcc>, ()> {
macro_rules! emit_error {
($msg: tt, $($fmt: tt)*) => {
span_invalid_monomorphization_error(
bx.sess(), span,
&format!(concat!("invalid monomorphization of `{}` intrinsic: ", $msg),
name, $($fmt)*));
}
}
macro_rules! return_error { macro_rules! return_error {
($($fmt: tt)*) => { ($err:expr) => {
{ {
emit_error!($($fmt)*); bx.sess().emit_err($err);
return Err(()); return Err(());
} }
} }
} }
let (elem_ty_str, elem_ty) = let (elem_ty_str, elem_ty) =
if let ty::Float(f) = in_elem.kind() { if let ty::Float(f) = in_elem.kind() {
let elem_ty = bx.cx.type_float_from_ty(*f); let elem_ty = bx.cx.type_float_from_ty(*f);
@ -427,16 +387,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
32 => ("f", elem_ty), 32 => ("f", elem_ty),
64 => ("", elem_ty), 64 => ("", elem_ty),
_ => { _ => {
return_error!( // Can we pass elem_ty directly?
"unsupported element type `{}` of floating-point vector `{}`", return_error!(InvalidMonomorphizationInvalidFloatVector { span, name, elem_ty: f.name_str(), vec_ty: in_ty });
f.name_str(),
in_ty
);
} }
} }
} }
else { else {
return_error!("`{}` is not a floating-point type", in_ty); return_error!(InvalidMonomorphizationNotFloat { span, name, ty: in_ty });
}; };
let vec_ty = bx.cx.type_vector(elem_ty, in_len); let vec_ty = bx.cx.type_vector(elem_ty, in_len);
@ -459,7 +416,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
sym::simd_fsqrt => "sqrt", sym::simd_fsqrt => "sqrt",
sym::simd_round => "round", sym::simd_round => "round",
sym::simd_trunc => "trunc", sym::simd_trunc => "trunc",
_ => return_error!("unrecognized intrinsic `{}`", name), _ => return_error!(InvalidMonomorphizationUnrecognized { span, name })
}; };
let builtin_name = format!("{}{}", intr_name, elem_ty_str); let builtin_name = format!("{}{}", intr_name, elem_ty_str);
let funcs = bx.cx.functions.borrow(); let funcs = bx.cx.functions.borrow();
@ -813,10 +770,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
})* })*
_ => {}, _ => {},
} }
require!(false, return_error!(InvalidMonomorphizationUnsupportedOperation { span, name, in_ty, in_elem })
"unsupported operation on `{}` with element `{}`",
in_ty,
in_elem)
})* })*
} }
} }
@ -836,13 +790,25 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)), ty::Int(i) => (true, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_int_from_ty(i)),
ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)), ty::Uint(i) => (false, i.bit_width().unwrap_or(ptr_bits) / 8, bx.cx.type_uint_from_ty(i)),
_ => { _ => {
return_error!( return_error!(InvalidMonomorphizationExpectedSignedUnsigned {
"expected element type `{}` of vector type `{}` \ span,
to be a signed or unsigned integer type", name,
arg_tys[0].simd_size_and_type(bx.tcx()).1, elem_ty: arg_tys[0].simd_size_and_type(bx.tcx()).1,
arg_tys[0] vec_ty: arg_tys[0],
); });
} }
};
let builtin_name =
match (signed, is_add, in_len, elem_width) {
(true, true, 32, 8) => "__builtin_ia32_paddsb256", // TODO(antoyo): cast arguments to unsigned.
(false, true, 32, 8) => "__builtin_ia32_paddusb256",
(true, true, 16, 16) => "__builtin_ia32_paddsw256",
(false, true, 16, 16) => "__builtin_ia32_paddusw256",
(true, false, 16, 16) => "__builtin_ia32_psubsw256",
(false, false, 16, 16) => "__builtin_ia32_psubusw256",
(true, false, 32, 8) => "__builtin_ia32_psubsb256",
(false, false, 32, 8) => "__builtin_ia32_psubusb256",
_ => unimplemented!("signed: {}, is_add: {}, in_len: {}, elem_width: {}", signed, is_add, in_len, elem_width),
}; };
let result = let result =
@ -924,10 +890,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
if name == sym::$name { if name == sym::$name {
require!( require!(
ret_ty == in_elem, ret_ty == in_elem,
"expected return type `{}` (element of input `{}`), found `{}`", InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
in_elem,
in_ty,
ret_ty
); );
return match in_elem.kind() { return match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => { ty::Int(_) | ty::Uint(_) => {
@ -951,13 +914,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op)) Ok(bx.vector_reduce_op(args[0].immediate(), $vec_op))
} }
} }
_ => return_error!( _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
"unsupported {} from `{}` with element `{}` to `{}`",
sym::$name,
in_ty,
in_elem,
ret_ty
),
}; };
} }
}; };
@ -998,21 +955,12 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
if name == sym::$name { if name == sym::$name {
require!( require!(
ret_ty == in_elem, ret_ty == in_elem,
"expected return type `{}` (element of input `{}`), found `{}`", InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
in_elem,
in_ty,
ret_ty
); );
return match in_elem.kind() { return match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())), ty::Int(_) | ty::Uint(_) => Ok(bx.$int_red(args[0].immediate())),
ty::Float(_) => Ok(bx.$float_red(args[0].immediate())), ty::Float(_) => Ok(bx.$float_red(args[0].immediate())),
_ => return_error!( _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
"unsupported {} from `{}` with element `{}` to `{}`",
sym::$name,
in_ty,
in_elem,
ret_ty
),
}; };
} }
}; };
@ -1030,22 +978,13 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
let input = if !$boolean { let input = if !$boolean {
require!( require!(
ret_ty == in_elem, ret_ty == in_elem,
"expected return type `{}` (element of input `{}`), found `{}`", InvalidMonomorphizationReturnType { span, name, in_elem, in_ty, ret_ty }
in_elem,
in_ty,
ret_ty
); );
args[0].immediate() args[0].immediate()
} else { } else {
match in_elem.kind() { match in_elem.kind() {
ty::Int(_) | ty::Uint(_) => {} ty::Int(_) | ty::Uint(_) => {}
_ => return_error!( _ => return_error!(InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }),
"unsupported {} from `{}` with element `{}` to `{}`",
sym::$name,
in_ty,
in_elem,
ret_ty
),
} }
args[0].immediate() args[0].immediate()
@ -1056,11 +995,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>,
Ok(if !$boolean { r } else { bx.icmp(IntPredicate::IntNE, r, bx.context.new_rvalue_zero(r.get_type())) }) Ok(if !$boolean { r } else { bx.icmp(IntPredicate::IntNE, r, bx.context.new_rvalue_zero(r.get_type())) })
} }
_ => return_error!( _ => return_error!(
"unsupported {} from `{}` with element `{}` to `{}`", InvalidMonomorphizationUnsupportedElement { span, name, in_ty, elem_ty: in_elem, ret_ty }
sym::$name,
in_ty,
in_elem,
ret_ty
), ),
}; };
} }