From 1ae82a8c43f396e26b8ad554bd8ed61c7136e64e Mon Sep 17 00:00:00 2001 From: Daniel Schwartz-Narbonne Date: Wed, 30 Jun 2021 06:16:16 -0400 Subject: [PATCH] use codegen_unimplemented() for the try intrinsic (#275) * use codegen_unimplemented() for the try intrinsic * Additional unit test --- .../rustc_codegen_llvm/src/gotoc/intrinsic.rs | 26 +++++++++++++------ .../rustc_codegen_llvm/src/gotoc/rvalue.rs | 10 ++++++- .../cbmc/Intrinsics/fixme_catch_unwind.rs | 18 +++++++++++++ src/test/cbmc/Intrinsics/fixme_try.rs | 18 +++++++++++++ 4 files changed, 63 insertions(+), 9 deletions(-) create mode 100644 src/test/cbmc/Intrinsics/fixme_catch_unwind.rs create mode 100644 src/test/cbmc/Intrinsics/fixme_try.rs diff --git a/compiler/rustc_codegen_llvm/src/gotoc/intrinsic.rs b/compiler/rustc_codegen_llvm/src/gotoc/intrinsic.rs index e78522335683..7fc82bc50642 100644 --- a/compiler/rustc_codegen_llvm/src/gotoc/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/gotoc/intrinsic.rs @@ -42,6 +42,14 @@ impl<'tcx> GotocCtx<'tcx> { let intrinsic = self.symbol_name(instance); let intrinsic = intrinsic.as_str(); let loc = self.codegen_span_option2(span); + debug!( + "codegen_intrinsic:\n\tinstance {:?}\n\tfargs {:?}\n\tp {:?}\n\tspan {:?}", + instance, fargs, p, span + ); + let sig = instance.ty(self.tcx, ty::ParamEnv::reveal_all()).fn_sig(self.tcx); + let sig = self.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); + let ret_ty = self.monomorphize(sig.output()); + let cbmc_ret_ty = self.codegen_ty(ret_ty); /// https://doc.rust-lang.org/core/intrinsics/fn.copy.html /// https://doc.rust-lang.org/core/intrinsics/fn.copy_nonoverlapping.html @@ -171,6 +179,13 @@ impl<'tcx> GotocCtx<'tcx> { }}; } + macro_rules! codegen_unimplemented_intrinsic { + ($url: expr) => {{ + let e = self.codegen_unimplemented(intrinsic, cbmc_ret_ty, loc, $url); + self.codegen_expr_to_place(p, e) + }}; + } + // Most atomic intrinsics do: // 1. Perform an operation on a primary argument (e.g., addition) // 2. Return the previous value of the primary argument @@ -202,14 +217,6 @@ impl<'tcx> GotocCtx<'tcx> { }}; } - debug!( - "codegen_intrinsic:\n\tinstance {:?}\n\tfargs {:?}\n\tp {:?}\n\tspan {:?}", - instance, fargs, p, span - ); - let sig = instance.ty(self.tcx, ty::ParamEnv::reveal_all()).fn_sig(self.tcx); - let sig = self.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig); - let ret_ty = self.monomorphize(sig.output()); - match intrinsic { "abort" => Stmt::assert_false("abort intrinsic", loc), "add_with_overflow" => codegen_op_with_overflow!(add_overflow), @@ -394,6 +401,9 @@ impl<'tcx> GotocCtx<'tcx> { "transmute" => self.codegen_intrinsic_transmute(fargs, ret_ty, p), "truncf32" => codegen_simple_intrinsic!(Truncf), "truncf64" => codegen_simple_intrinsic!(Trunc), + "try" => { + codegen_unimplemented_intrinsic!("https://github.com/model-checking/rmc/issues/267") + } "type_id" => codegen_intrinsic_const!(), "type_name" => codegen_intrinsic_const!(), "unaligned_volatile_load" => { diff --git a/compiler/rustc_codegen_llvm/src/gotoc/rvalue.rs b/compiler/rustc_codegen_llvm/src/gotoc/rvalue.rs index b9cd0d77d88e..3d4c4e87eee3 100644 --- a/compiler/rustc_codegen_llvm/src/gotoc/rvalue.rs +++ b/compiler/rustc_codegen_llvm/src/gotoc/rvalue.rs @@ -628,7 +628,15 @@ impl<'tcx> GotocCtx<'tcx> { match k { PointerCast::ReifyFnPointer => self.codegen_operand(o).address_of(), PointerCast::UnsafeFnPointer => self.codegen_operand(o), - PointerCast::ClosureFnPointer(_) => unimplemented!(), + PointerCast::ClosureFnPointer(_) => { + let dest_typ = self.codegen_ty(t); + self.codegen_unimplemented( + "PointerCast::ClosureFnPointer", + dest_typ, + Location::none(), + "https://github.com/model-checking/rmc/issues/274", + ) + } PointerCast::MutToConstPointer => self.codegen_operand(o), PointerCast::ArrayToPointer => { // TODO: I am not sure whether it is correct or not. diff --git a/src/test/cbmc/Intrinsics/fixme_catch_unwind.rs b/src/test/cbmc/Intrinsics/fixme_catch_unwind.rs new file mode 100644 index 000000000000..aa7e9e980db6 --- /dev/null +++ b/src/test/cbmc/Intrinsics/fixme_catch_unwind.rs @@ -0,0 +1,18 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR MIT + +// https://doc.rust-lang.org/std/panic/fn.catch_unwind.html +// Stable way of calling the `try` intrinsic. +use std::panic; + +fn main() { + let result = panic::catch_unwind(|| { + println!("hello!"); + }); + assert!(result.is_ok()); + + let result = panic::catch_unwind(|| { + panic!("oh no!"); + }); + assert!(result.is_err()); +} diff --git a/src/test/cbmc/Intrinsics/fixme_try.rs b/src/test/cbmc/Intrinsics/fixme_try.rs new file mode 100644 index 000000000000..e465d38c1543 --- /dev/null +++ b/src/test/cbmc/Intrinsics/fixme_try.rs @@ -0,0 +1,18 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 OR MIT + +// See discussion on https://github.com/model-checking/rmc/issues/267 +#![feature(core_intrinsics)] +use std::intrinsics::r#try; + +fn main() { + unsafe { + // Rust will make a best-effort to swallow the panic, and then execute the cleanup function. + // However, my understanding is that failure is still possible, since its just a best-effort + r#try( + |_a: *mut u8| panic!("foo"), + std::ptr::null_mut(), + |_a: *mut u8, _b: *mut u8| println!("bar"), + ); + } +}