use crate::context::CodegenCx;
use crate::llvm::Value;
use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods};
use rustc_session::config::DebugInfo;
impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
pub(crate) fn declare_intrinsic(&self, key: &str) -> Option<&'ll Value> {
let map = self.intrinsics_map.borrow();
let (args, ret) = map.get(key)?;
Some(self.insert_intrinsic(key.to_string(), Some(args), ret))
}
#[rustfmt::skip] pub(crate) fn build_intrinsics_map(&mut self) {
let mut map = self.intrinsics_map.borrow_mut();
let mut remapped = self.remapped_integer_args.borrow_mut();
macro_rules! ifn {
($map:expr, $($name:literal)|*, fn($($arg:expr),*) -> $ret:expr) => {
for name in [$($name),*] {
map.insert(name, (vec![$($arg),*], $ret));
}
};
}
let real_t_i128 = self.type_i128();
let real_t_i128_i1 = self.type_struct(&[real_t_i128, self.type_i1()], false);
let i8p = self.type_i8p();
let void = self.type_void();
let i1 = self.type_i1();
let t_i8 = self.type_i8();
let t_i16 = self.type_i16();
let t_i32 = self.type_i32();
let t_i64 = self.type_i64();
let t_i128 = self.type_vector(t_i64, 2);
let t_f32 = self.type_f32();
let t_f64 = self.type_f64();
let t_isize = self.type_isize();
let t_i8_i1 = self.type_struct(&[t_i8, i1], false);
let t_i16_i1 = self.type_struct(&[t_i16, i1], false);
let t_i32_i1 = self.type_struct(&[t_i32, i1], false);
let t_i64_i1 = self.type_struct(&[t_i64, i1], false);
let t_i128_i1 = self.type_struct(&[t_i128, i1], false);
let voidp = self.voidp();
ifn!(map, "llvm.trap" | "llvm.sideeffect", fn() -> void);
ifn!(map, "llvm.assume", fn(i1) -> void);
ifn!(map, "llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
ifn!(map, "llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> t_i16_i1);
ifn!(map, "llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> t_i32_i1);
ifn!(map, "llvm.sadd.with.overflow.i64", fn(t_i64, t_i64) -> t_i64_i1);
ifn!(map, "llvm.uadd.with.overflow.i16", fn(t_i16, t_i16) -> t_i16_i1);
ifn!(map, "llvm.uadd.with.overflow.i32", fn(t_i32, t_i32) -> t_i32_i1);
ifn!(map, "llvm.uadd.with.overflow.i64", fn(t_i64, t_i64) -> t_i64_i1);
ifn!(map, "llvm.ssub.with.overflow.i16", fn(t_i16, t_i16) -> t_i16_i1);
ifn!(map, "llvm.ssub.with.overflow.i32", fn(t_i32, t_i32) -> t_i32_i1);
ifn!(map, "llvm.ssub.with.overflow.i64", fn(t_i64, t_i64) -> t_i64_i1);
ifn!(map, "llvm.usub.with.overflow.i16", fn(t_i16, t_i16) -> t_i16_i1);
ifn!(map, "llvm.usub.with.overflow.i32", fn(t_i32, t_i32) -> t_i32_i1);
ifn!(map, "llvm.usub.with.overflow.i64", fn(t_i64, t_i64) -> t_i64_i1);
ifn!(map, "llvm.smul.with.overflow.i16", fn(t_i16, t_i16) -> t_i16_i1);
ifn!(map, "llvm.smul.with.overflow.i32", fn(t_i32, t_i32) -> t_i32_i1);
ifn!(map, "llvm.smul.with.overflow.i64", fn(t_i64, t_i64) -> t_i64_i1);
ifn!(map, "llvm.umul.with.overflow.i16", fn(t_i16, t_i16) -> t_i16_i1);
ifn!(map, "llvm.umul.with.overflow.i32", fn(t_i32, t_i32) -> t_i32_i1);
ifn!(map, "llvm.umul.with.overflow.i64", fn(t_i64, t_i64) -> t_i64_i1);
let i128_checked_binops = [
"__nvvm_i128_addo",
"__nvvm_u128_addo",
"__nvvm_i128_subo",
"__nvvm_u128_subo",
"__nvvm_i128_mulo",
"__nvvm_u128_mulo"
];
for binop in i128_checked_binops {
map.insert(binop, (vec![t_i128, t_i128], t_i128_i1));
let llfn_ty = self.type_func(&[t_i128, t_i128], t_i128_i1);
remapped.insert(llfn_ty, (Some(real_t_i128_i1), vec![(0, real_t_i128), (1, real_t_i128)]));
}
let i128_saturating_ops = [
"llvm.sadd.sat.i128",
"llvm.uadd.sat.i128",
"llvm.ssub.sat.i128",
"llvm.usub.sat.i128",
];
for binop in i128_saturating_ops {
map.insert(binop, (vec![t_i128, t_i128], t_i128));
let llfn_ty = self.type_func(&[t_i128, t_i128], t_i128);
remapped.insert(llfn_ty, (Some(real_t_i128), vec![(0, real_t_i128), (1, real_t_i128)]));
}
ifn!(map, "__nvvm_i8_addo", fn(t_i8, t_i8) -> t_i8_i1);
ifn!(map, "__nvvm_u8_addo", fn(t_i8, t_i8) -> t_i8_i1);
ifn!(map, "__nvvm_i8_subo", fn(t_i8, t_i8) -> t_i8_i1);
ifn!(map, "__nvvm_u8_subo", fn(t_i8, t_i8) -> t_i8_i1);
ifn!(map, "__nvvm_i8_mulo", fn(t_i8, t_i8) -> t_i8_i1);
ifn!(map, "__nvvm_u8_mulo", fn(t_i8, t_i8) -> t_i8_i1);
ifn!(map, "llvm.sadd.sat.i8", fn(t_i8, t_i8) -> t_i8);
ifn!(map, "llvm.sadd.sat.i16", fn(t_i16, t_i16) -> t_i16);
ifn!(map, "llvm.sadd.sat.i32", fn(t_i32, t_i32) -> t_i32);
ifn!(map, "llvm.sadd.sat.i64", fn(t_i64, t_i64) -> t_i64);
ifn!(map, "llvm.uadd.sat.i8", fn(t_i8, t_i8) -> t_i8);
ifn!(map, "llvm.uadd.sat.i16", fn(t_i16, t_i16) -> t_i16);
ifn!(map, "llvm.uadd.sat.i32", fn(t_i32, t_i32) -> t_i32);
ifn!(map, "llvm.uadd.sat.i64", fn(t_i64, t_i64) -> t_i64);
ifn!(map, "llvm.ssub.sat.i8", fn(t_i8, t_i8) -> t_i8);
ifn!(map, "llvm.ssub.sat.i16", fn(t_i16, t_i16) -> t_i16);
ifn!(map, "llvm.ssub.sat.i32", fn(t_i32, t_i32) -> t_i32);
ifn!(map, "llvm.ssub.sat.i64", fn(t_i64, t_i64) -> t_i64);
ifn!(map, "llvm.usub.sat.i8", fn(t_i8, t_i8) -> t_i8);
ifn!(map, "llvm.usub.sat.i16", fn(t_i16, t_i16) -> t_i16);
ifn!(map, "llvm.usub.sat.i32", fn(t_i32, t_i32) -> t_i32);
ifn!(map, "llvm.usub.sat.i64", fn(t_i64, t_i64) -> t_i64);
ifn!(map, "llvm.fshl.i8", fn(t_i8, t_i8, t_i8) -> t_i8);
ifn!(map, "llvm.fshl.i16", fn(t_i16, t_i16, t_i16) -> t_i16);
ifn!(map, "llvm.fshl.i32", fn(t_i32, t_i32, t_i32) -> t_i32);
ifn!(map, "llvm.fshl.i64", fn(t_i64, t_i64, t_i64) -> t_i64);
ifn!(map, "llvm.fshr.i8", fn(t_i8, t_i8, t_i8) -> t_i8);
ifn!(map, "llvm.fshr.i16", fn(t_i16, t_i16, t_i16) -> t_i16);
ifn!(map, "llvm.fshr.i32", fn(t_i32, t_i32, t_i32) -> t_i32);
ifn!(map, "llvm.fshr.i64", fn(t_i64, t_i64, t_i64) -> t_i64);
ifn!(map, "llvm.ctpop.i8", fn(t_i8) -> t_i8);
ifn!(map, "llvm.ctpop.i16", fn(t_i16) -> t_i16);
ifn!(map, "llvm.ctpop.i32", fn(t_i32) -> t_i32);
ifn!(map, "llvm.ctpop.i64", fn(t_i64) -> t_i64);
ifn!(map, "llvm.bitreverse.i8", fn(t_i8) -> t_i8);
ifn!(map, "llvm.bitreverse.i16", fn(t_i16) -> t_i16);
ifn!(map, "llvm.bitreverse.i32", fn(t_i32) -> t_i32);
ifn!(map, "llvm.bitreverse.i64", fn(t_i64) -> t_i64);
ifn!(map, "llvm.bswap.i16", fn(t_i16) -> t_i16);
ifn!(map, "llvm.bswap.i32", fn(t_i32) -> t_i32);
ifn!(map, "llvm.bswap.i64", fn(t_i64) -> t_i64);
ifn!(map, "llvm.ctlz.i8", fn(t_i8, i1) -> t_i8);
ifn!(map, "llvm.ctlz.i16", fn(t_i16, i1) -> t_i16);
ifn!(map, "llvm.ctlz.i32", fn(t_i32, i1) -> t_i32);
ifn!(map, "llvm.ctlz.i64", fn(t_i64, i1) -> t_i64);
ifn!(map, "llvm.cttz.i8", fn(t_i8, i1) -> t_i8);
ifn!(map, "llvm.cttz.i16", fn(t_i16, i1) -> t_i16);
ifn!(map, "llvm.cttz.i32", fn(t_i32, i1) -> t_i32);
ifn!(map, "llvm.cttz.i64", fn(t_i64, i1) -> t_i64);
ifn!(map, "llvm.lifetime.start.p0i8", fn(t_i64, i8p) -> void);
ifn!(map, "llvm.lifetime.end.p0i8", fn(t_i64, i8p) -> void);
ifn!(map, "llvm.expect.i1", fn(i1, i1) -> i1);
ifn!(map, "llvm.prefetch", fn(i8p, t_i32, t_i32, t_i32) -> void);
ifn!(map, "memcmp", fn(i8p, i8p, t_isize) -> t_i32);
ifn!(map, "llvm.va_start", fn(i8p) -> void);
ifn!(map, "llvm.va_end", fn(i8p) -> void);
ifn!(map, "llvm.va_copy", fn(i8p, i8p) -> void);
if self.tcx.sess.opts.debuginfo != DebugInfo::None {
ifn!(map, "llvm.dbg.declare", fn(self.type_metadata(), self.type_metadata()) -> void);
ifn!(map, "llvm.dbg.value", fn(self.type_metadata(), t_i64, self.type_metadata()) -> void);
}
ifn!(map, "vprintf", fn(i8p, voidp) -> t_i32);
ifn!(map, "__nv_abs", fn(t_i32) -> t_i32);
ifn!(
map,
"__nv_acos" |
"__nv_acosh" |
"__nv_asin" |
"__nv_asinh" |
"__nv_atan" |
"__nv_atanh" |
"__nv_cbrt" |
"__nv_ceil" |
"__nv_cos" |
"__nv_cosh" |
"__nv_cospi" |
"__nv_drcp_rd" |
"__nv_drcp_rn" |
"__nv_drcp_ru" |
"__nv_drcp_rz" |
"__nv_dsqrt_rd" |
"__nv_dsqrt_rn" |
"__nv_dsqrt_ru" |
"__nv_dsqrt_rz" |
"__nv_erf" |
"__nv_erfc" |
"__nv_erfcinv" |
"__nv_erfcx" |
"__nv_erfinv" |
"__nv_exp" |
"__nv_exp10" |
"__nv_exp2" |
"__nv_expm1" |
"__nv_fabs" |
"__nv_floor" |
"__nv_j0" |
"__nv_j1" |
"__nv_lgamma" |
"__nv_log" |
"__nv_log10" |
"__nv_log1p" |
"__nv_log2" |
"__nv_logb" |
"__nv_nearbyint" |
"__nv_normcdf" |
"__nv_normcdfinv" |
"__nv_rcbrt" |
"__nv_rint" |
"__nv_round" |
"__nv_rsqrt" |
"__nv_sin" |
"__nv_sinh" |
"__nv_sinpi" |
"__nv_sqrt" |
"__nv_tan" |
"__nv_tanh" |
"__nv_tgamma" |
"__nv_trunc" |
"__nv_y0" |
"__nv_y1",
fn(t_f64) -> t_f64
);
ifn!(
map,
"__nv_acosf" |
"__nv_acoshf" |
"__nv_asinf" |
"__nv_asinhf" |
"__nv_atanf" |
"__nv_atanhf" |
"__nv_cbrtf" |
"__nv_ceilf" |
"__nv_cosf" |
"__nv_coshf" |
"__nv_cospif" |
"__nv_erff" |
"__nv_erfcf" |
"__nv_erfcinvf" |
"__nv_erfcxf" |
"__nv_erfinvf" |
"__nv_expf" |
"__nv_exp10f" |
"__nv_exp2f" |
"__nv_expm1f" |
"__nv_fabsf" |
"__nv_floorf" |
"__nv_j0f" |
"__nv_j1f" |
"__nv_lgammaf" |
"__nv_logf" |
"__nv_log10f" |
"__nv_log1pf" |
"__nv_log2f" |
"__nv_logbf" |
"__nv_nearbyintf" |
"__nv_normcdff" |
"__nv_normcdfinvf" |
"__nv_rcbrtf" |
"__nv_rintf" |
"__nv_roundf" |
"__nv_rsqrtf" |
"__nv_sinf" |
"__nv_sinhf" |
"__nv_sinpif" |
"__nv_sqrtf" |
"__nv_tanf" |
"__nv_tanhf" |
"__nv_tgammaf" |
"__nv_truncf" |
"__nv_y0f" |
"__nv_y1f",
fn(t_f32) -> t_f32
);
ifn!(
map,
"__nv_atan2" |
"__nv_copysign" |
"__nv_dadd_rd" |
"__nv_dadd_rn" |
"__nv_dadd_ru" |
"__nv_dadd_rz" |
"__nv_ddiv_rd" |
"__nv_ddiv_rn" |
"__nv_ddiv_ru" |
"__nv_ddiv_rz" |
"__nv_dmul_rd" |
"__nv_dmul_rn" |
"__nv_dmul_ru" |
"__nv_dmul_rz" |
"__nv_fdim" |
"__nv_fmax" |
"__nv_fmin" |
"__nv_fmod" |
"__nv_hypot" |
"__nv_nextafter" |
"__nv_pow" |
"__nv_remainder",
fn(t_f64, t_f64) -> t_f64
);
ifn!(
map,
"__nv_atan2f" |
"__nv_copysignf" |
"__nv_fadd_rd" |
"__nv_fadd_rn" |
"__nv_fadd_ru" |
"__nv_fadd_rz" |
"__nv_fast_fdividef" |
"__nv_fast_powf" |
"__nv_fdimf" |
"__nv_fdiv_rd" |
"__nv_fdiv_rn" |
"__nv_fdiv_ru" |
"__nv_fdiv_rz" |
"__nv_fmaxf" |
"__nv_fminf" |
"__nv_fmodf" |
"__nv_fmul_rd" |
"__nv_fmul_rn" |
"__nv_fmul_ru" |
"__nv_fmul_rz" |
"__nv_fsub_rd" |
"__nv_fsub_rn" |
"__nv_fsub_ru" |
"__nv_fsub_rz" |
"__nv_hypotf" |
"__nv_nextafterf" |
"__nv_powf" |
"__nv_remainderf",
fn(t_f32, t_f32) -> t_f32
);
ifn!(
map,
"__nv_powi",
fn(t_f64, t_i32) -> t_f64
);
ifn!(
map,
"__nv_powif",
fn(t_f32, t_i32) -> t_f32
);
ifn!(
map,
"__nv_fma",
fn(t_f64, t_f64, t_f64) -> t_f64
);
ifn!(
map,
"__nv_fmaf",
fn(t_f32, t_f32, t_f32) -> t_f32
);
ifn!(
map,
"__nv_yn",
fn(t_i32, t_f64) -> t_f64
);
ifn!(
map,
"__nv_ynf",
fn(t_i32, t_f32) -> t_f32
);
}
}