summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs')
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs122
1 files changed, 48 insertions, 74 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index e4ac89a7b..e74aabf2f 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -21,6 +21,8 @@ mod simd;
pub(crate) use cpuid::codegen_cpuid_call;
pub(crate) use llvm::codegen_llvm_intrinsic_call;
+use rustc_middle::ty;
+use rustc_middle::ty::layout::{HasParamEnv, ValidityRequirement};
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::SubstsRef;
use rustc_span::symbol::{kw, sym, Symbol};
@@ -200,7 +202,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
let mut res = fx.bcx.ins().bmask(int_ty, val);
if ty.is_float() {
- res = fx.bcx.ins().bitcast(ty, res);
+ res = codegen_bitcast(fx, ty, res);
}
res
@@ -217,22 +219,6 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
let intrinsic = fx.tcx.item_name(instance.def_id());
let substs = instance.substs;
- let target = if let Some(target) = target {
- target
- } else {
- // Insert non returning intrinsics here
- match intrinsic {
- sym::abort => {
- fx.bcx.ins().trap(TrapCode::User(0));
- }
- sym::transmute => {
- crate::base::codegen_panic(fx, "Transmuting to uninhabited type.", source_info);
- }
- _ => unimplemented!("unsupported intrinsic {}", intrinsic),
- }
- return;
- };
-
if intrinsic.as_str().starts_with("simd_") {
self::simd::codegen_simd_intrinsic_call(
fx,
@@ -240,12 +226,11 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
substs,
args,
destination,
+ target.expect("target for simd intrinsic"),
source_info.span,
);
- let ret_block = fx.get_block(target);
- fx.bcx.ins().jump(ret_block, &[]);
} else if codegen_float_intrinsic_call(fx, intrinsic, args, destination) {
- let ret_block = fx.get_block(target);
+ let ret_block = fx.get_block(target.expect("target for float intrinsic"));
fx.bcx.ins().jump(ret_block, &[]);
} else {
codegen_regular_intrinsic_call(
@@ -255,7 +240,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
substs,
args,
destination,
- Some(target),
+ target,
source_info,
);
}
@@ -382,6 +367,10 @@ fn codegen_regular_intrinsic_call<'tcx>(
let usize_layout = fx.layout_of(fx.tcx.types.usize);
match intrinsic {
+ sym::abort => {
+ fx.bcx.ins().trap(TrapCode::User(0));
+ return;
+ }
sym::likely | sym::unlikely => {
intrinsic_args!(fx, args => (a); intrinsic);
@@ -505,20 +494,6 @@ fn codegen_regular_intrinsic_call<'tcx>(
let res = crate::num::codegen_int_binop(fx, bin_op, x, y);
ret.write_cvalue(fx, res);
}
- sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
- intrinsic_args!(fx, args => (x, y); intrinsic);
-
- assert_eq!(x.layout().ty, y.layout().ty);
- let bin_op = match intrinsic {
- sym::add_with_overflow => BinOp::Add,
- sym::sub_with_overflow => BinOp::Sub,
- sym::mul_with_overflow => BinOp::Mul,
- _ => unreachable!(),
- };
-
- let res = crate::num::codegen_checked_int_binop(fx, bin_op, x, y);
- ret.write_cvalue(fx, res);
- }
sym::saturating_add | sym::saturating_sub => {
intrinsic_args!(fx, args => (lhs, rhs); intrinsic);
@@ -579,6 +554,11 @@ fn codegen_regular_intrinsic_call<'tcx>(
sym::transmute => {
intrinsic_args!(fx, args => (from); intrinsic);
+ if ret.layout().abi.is_uninhabited() {
+ crate::base::codegen_panic(fx, "Transmuting to uninhabited type.", source_info);
+ return;
+ }
+
ret.write_cvalue_transmute(fx, from);
}
sym::write_bytes | sym::volatile_set_memory => {
@@ -647,46 +627,40 @@ fn codegen_regular_intrinsic_call<'tcx>(
sym::assert_inhabited | sym::assert_zero_valid | sym::assert_mem_uninitialized_valid => {
intrinsic_args!(fx, args => (); intrinsic);
- let layout = fx.layout_of(substs.type_at(0));
- if layout.abi.is_uninhabited() {
- with_no_trimmed_paths!({
- crate::base::codegen_panic(
- fx,
- &format!("attempted to instantiate uninhabited type `{}`", layout.ty),
- source_info,
- )
- });
- return;
- }
-
- if intrinsic == sym::assert_zero_valid && !fx.tcx.permits_zero_init(layout) {
- with_no_trimmed_paths!({
- crate::base::codegen_panic(
- fx,
- &format!(
- "attempted to zero-initialize type `{}`, which is invalid",
- layout.ty
- ),
- source_info,
- );
- });
- return;
- }
+ let ty = substs.type_at(0);
- if intrinsic == sym::assert_mem_uninitialized_valid
- && !fx.tcx.permits_uninit_init(layout)
- {
- with_no_trimmed_paths!({
- crate::base::codegen_panic(
- fx,
- &format!(
- "attempted to leave type `{}` uninitialized, which is invalid",
- layout.ty
- ),
- source_info,
- )
- });
- return;
+ let requirement = ValidityRequirement::from_intrinsic(intrinsic);
+
+ if let Some(requirement) = requirement {
+ let do_panic = !fx
+ .tcx
+ .check_validity_requirement((requirement, fx.param_env().and(ty)))
+ .expect("expect to have layout during codegen");
+
+ if do_panic {
+ let layout = fx.layout_of(ty);
+
+ with_no_trimmed_paths!({
+ crate::base::codegen_panic_nounwind(
+ fx,
+ &if layout.abi.is_uninhabited() {
+ format!("attempted to instantiate uninhabited type `{}`", layout.ty)
+ } else if requirement == ValidityRequirement::Zero {
+ format!(
+ "attempted to zero-initialize type `{}`, which is invalid",
+ layout.ty
+ )
+ } else {
+ format!(
+ "attempted to leave type `{}` uninitialized, which is invalid",
+ layout.ty
+ )
+ },
+ source_info,
+ )
+ });
+ return;
+ }
}
}