diff --git a/src/intrinsics.rs b/src/intrinsics.rs index 251299dcdbe..042a0934709 100644 --- a/src/intrinsics.rs +++ b/src/intrinsics.rs @@ -2,42 +2,50 @@ use crate::prelude::*; use rustc::ty::subst::SubstsRef; -macro_rules! intrinsic_pat { +macro intrinsic_pat { (_) => { _ - }; + }, ($name:ident) => { stringify!($name) + }, + ($name:literal) => { + stringify!($name) + }, + ($x:ident . $($xs:tt).*) => { + concat!(stringify!($x), ".", intrinsic_pat!($($xs).*)) } } -macro_rules! intrinsic_arg { +macro intrinsic_arg { (o $fx:expr, $arg:ident) => { $arg - }; + }, (c $fx:expr, $arg:ident) => { trans_operand($fx, $arg) - }; + }, (v $fx:expr, $arg:ident) => { trans_operand($fx, $arg).load_scalar($fx) - }; + } } -macro_rules! intrinsic_substs { - ($substs:expr, $index:expr,) => {}; +macro intrinsic_substs { + ($substs:expr, $index:expr,) => {}, ($substs:expr, $index:expr, $first:ident $(,$rest:ident)*) => { let $first = $substs.type_at($index); intrinsic_substs!($substs, $index+1, $($rest),*); - }; + } } -macro_rules! intrinsic_match { - ($fx:expr, $intrinsic:expr, $substs:expr, $args:expr, $( - $($name:tt)|+ $(if $cond:expr)?, $(<$($subst:ident),*>)? ($($a:ident $arg:ident),*) $content:block; +pub macro intrinsic_match { + ($fx:expr, $intrinsic:expr, $substs:expr, $args:expr, + _ => $unknown:block; + $( + $($($name:tt).*)|+ $(if $cond:expr)?, $(<$($subst:ident),*>)? ($($a:ident $arg:ident),*) $content:block; )*) => { match $intrinsic { $( - $(intrinsic_pat!($name))|* $(if $cond)? => { + $(intrinsic_pat!($($name).*))|* $(if $cond)? => { #[allow(unused_parens, non_snake_case)] { $( @@ -57,9 +65,9 @@ macro_rules! intrinsic_match { } } )* - _ => unimpl!("unsupported intrinsic {}", $intrinsic), + _ => $unknown, } - }; + } } macro_rules! call_intrinsic_match { @@ -122,7 +130,7 @@ macro_rules! atomic_minmax { }; } -fn lane_type_and_count<'tcx>( +pub fn lane_type_and_count<'tcx>( fx: &FunctionCx<'_, 'tcx, impl Backend>, layout: TyLayout<'tcx>, intrinsic: &str, @@ -282,6 +290,9 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>( intrinsic_match! { fx, intrinsic, substs, args, + _ => { + unimpl!("unsupported intrinsic {}", intrinsic) + }; assume, (c _a) {}; likely | unlikely, (c a) { diff --git a/src/llvm_intrinsics.rs b/src/llvm_intrinsics.rs index 1ffd43bb780..bb993298411 100644 --- a/src/llvm_intrinsics.rs +++ b/src/llvm_intrinsics.rs @@ -9,8 +9,50 @@ pub fn codegen_llvm_intrinsic_call<'a, 'tcx: 'a>( args: &[mir::Operand<'tcx>], destination: Option<(CPlace<'tcx>, BasicBlock)>, ) { - fx.tcx.sess.warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic)); - crate::trap::trap_unimplemented(fx, intrinsic); + let ret = match destination { + Some((place, _)) => place, + None => { + // Insert non returning intrinsics here + match intrinsic { + "abort" => { + trap_panic(fx, "Called intrinsic::abort."); + } + "unreachable" => { + trap_unreachable(fx, "[corruption] Called intrinsic::unreachable."); + } + _ => unimplemented!("unsupported instrinsic {}", intrinsic), + } + return; + } + }; + + crate::intrinsics::intrinsic_match! { + fx, intrinsic, substs, args, + _ => { + fx.tcx.sess.warn(&format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic)); + crate::trap::trap_unimplemented(fx, intrinsic); + }; + + // Used by _mm_movemask_epi8 + llvm.x86.sse2.pmovmskb.128, (c a) { + let (lane_layout, lane_count) = crate::intrinsics::lane_type_and_count(fx, a.layout(), intrinsic); + assert_eq!(lane_layout.ty.sty, fx.tcx.types.i8.sty); + assert_eq!(lane_count, 16); + + let mut res = fx.bcx.ins().iconst(types::I32, 0); + + for lane in 0..16 { + let a_lane = a.value_field(fx, mir::Field::new(lane.try_into().unwrap())).load_scalar(fx); + let a_lane_sign = fx.bcx.ins().ushr_imm(a_lane, 7); // extract sign bit of 8bit int + let a_lane_sign = fx.bcx.ins().uextend(types::I32, a_lane_sign); + res = fx.bcx.ins().ishl_imm(res, 1); + res = fx.bcx.ins().bor(res, a_lane_sign); + } + + let res = CValue::by_val(res, fx.layout_of(fx.tcx.types.i32)); + ret.write_cvalue(fx, res); + }; + } if let Some((_, dest)) = destination { let ret_ebb = fx.get_ebb(dest); @@ -20,7 +62,6 @@ pub fn codegen_llvm_intrinsic_call<'a, 'tcx: 'a>( } } -// llvm.x86.sse2.pmovmskb.128 // llvm.x86.avx2.vperm2i128 // llvm.x86.ssse3.pshuf.b.128 // llvm.x86.avx2.pshuf.b