]> git.lizzy.rs Git - rust.git/blob - src/trap.rs
Rustup to rustc 1.42.0-nightly (3ebcfa145 2020-01-12)
[rust.git] / src / trap.rs
1 use crate::prelude::*;
2
3 fn codegen_print(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: &str) {
4     let puts = fx
5         .module
6         .declare_function(
7             "puts",
8             Linkage::Import,
9             &Signature {
10                 call_conv: CallConv::triple_default(fx.triple()),
11                 params: vec![AbiParam::new(pointer_ty(fx.tcx))],
12                 returns: vec![],
13             },
14         )
15         .unwrap();
16     let puts = fx.module.declare_func_in_func(puts, &mut fx.bcx.func);
17     #[cfg(debug_assertions)]
18     {
19         fx.add_entity_comment(puts, "puts");
20     }
21
22     let symbol_name = fx.tcx.symbol_name(fx.instance);
23     let real_msg = format!("trap at {:?} ({}): {}\0", fx.instance, symbol_name, msg);
24     let mut data_ctx = DataContext::new();
25     data_ctx.define(real_msg.as_bytes().to_vec().into_boxed_slice());
26     let msg_id = fx
27         .module
28         .declare_data(
29             &(symbol_name.name.as_str().to_string() + msg),
30             Linkage::Local,
31             false,
32             None,
33         )
34         .unwrap();
35
36     // Ignore DuplicateDefinition error, as the data will be the same
37     let _ = fx.module.define_data(msg_id, &data_ctx);
38
39     let local_msg_id = fx.module.declare_data_in_func(msg_id, fx.bcx.func);
40     #[cfg(debug_assertions)]
41     {
42         fx.add_entity_comment(local_msg_id, msg);
43     }
44     let msg_ptr = fx.bcx.ins().global_value(pointer_ty(fx.tcx), local_msg_id);
45     fx.bcx.ins().call(puts, &[msg_ptr]);
46 }
47
48 /// Use this when `rustc_codegen_llvm` would insert a call to the panic handler.
49 ///
50 /// Trap code: user0
51 pub fn trap_panic(
52     fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>,
53     msg: impl AsRef<str>,
54 ) {
55     codegen_print(fx, msg.as_ref());
56     fx.bcx.ins().trap(TrapCode::User(0));
57 }
58
59 /// Use this for example when a function call should never return. This will fill the current block,
60 /// so you can **not** add instructions to it afterwards.
61 ///
62 /// Trap code: user65535
63 pub fn trap_unreachable(
64     fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>,
65     msg: impl AsRef<str>,
66 ) {
67     codegen_print(fx, msg.as_ref());
68     fx.bcx.ins().trap(TrapCode::User(!0));
69 }
70
71 /// Use this when something is unimplemented, but `libcore` or `libstd` requires it to codegen.
72 /// Unlike `trap_unreachable` this will not fill the current block, so you **must** add instructions
73 /// to it afterwards.
74 ///
75 /// Trap code: user65535
76 pub fn trap_unimplemented(
77     fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>,
78     msg: impl AsRef<str>,
79 ) {
80     codegen_print(fx, msg.as_ref());
81     let true_ = fx.bcx.ins().iconst(types::I32, 1);
82     fx.bcx.ins().trapnz(true_, TrapCode::User(!0));
83 }
84
85 /// Like `trap_unreachable` but returns a fake value of the specified type.
86 ///
87 /// Trap code: user65535
88 pub fn trap_unreachable_ret_value<'tcx>(
89     fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>,
90     dest_layout: TyLayout<'tcx>,
91     msg: impl AsRef<str>,
92 ) -> CValue<'tcx> {
93     trap_unimplemented(fx, msg);
94     CValue::by_ref(Pointer::const_addr(fx, 0), dest_layout)
95 }