1 //! Emulate LLVM intrinsics
2
3 use crate::intrinsics::*;
4 use crate::prelude::*;
5
6 use rustc_middle::ty::subst::SubstsRef;
7
codegen_llvm_intrinsic_call<'tcx>( fx: &mut FunctionCx<'_, '_, 'tcx>, intrinsic: &str, substs: SubstsRef<'tcx>, args: &[mir::Operand<'tcx>], ret: CPlace<'tcx>, target: Option<BasicBlock>, )8 pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
9 fx: &mut FunctionCx<'_, '_, 'tcx>,
10 intrinsic: &str,
11 substs: SubstsRef<'tcx>,
12 args: &[mir::Operand<'tcx>],
13 ret: CPlace<'tcx>,
14 target: Option<BasicBlock>,
15 ) {
16 if intrinsic.starts_with("llvm.aarch64") {
17 return llvm_aarch64::codegen_aarch64_llvm_intrinsic_call(
18 fx, intrinsic, substs, args, ret, target,
19 );
20 }
21 if intrinsic.starts_with("llvm.x86") {
22 return llvm_x86::codegen_x86_llvm_intrinsic_call(fx, intrinsic, substs, args, ret, target);
23 }
24
25 match intrinsic {
26 _ if intrinsic.starts_with("llvm.ctlz.v") => {
27 intrinsic_args!(fx, args => (a); intrinsic);
28
29 simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
30 fx.bcx.ins().clz(lane)
31 });
32 }
33
34 _ if intrinsic.starts_with("llvm.ctpop.v") => {
35 intrinsic_args!(fx, args => (a); intrinsic);
36
37 simd_for_each_lane(fx, a, ret, &|fx, _lane_ty, _res_lane_ty, lane| {
38 fx.bcx.ins().popcnt(lane)
39 });
40 }
41
42 _ => {
43 fx.tcx
44 .sess
45 .warn(format!("unsupported llvm intrinsic {}; replacing with trap", intrinsic));
46 crate::trap::trap_unimplemented(fx, intrinsic);
47 return;
48 }
49 }
50
51 let dest = target.expect("all llvm intrinsics used by stdlib should return");
52 let ret_block = fx.get_block(dest);
53 fx.bcx.ins().jump(ret_block, &[]);
54 }
55