]>
Commit | Line | Data |
---|---|---|
29967ef6 XL |
1 | //! Helpers used to print a message and abort in case of certain panics and some detected UB. |
2 | ||
3 | use crate::prelude::*; | |
4 | ||
6a06907d | 5 | fn codegen_print(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) { |
29967ef6 | 6 | let puts = fx |
29967ef6 XL |
7 | .module |
8 | .declare_function( | |
9 | "puts", | |
10 | Linkage::Import, | |
11 | &Signature { | |
12 | call_conv: CallConv::triple_default(fx.triple()), | |
94222f64 | 13 | params: vec![AbiParam::new(fx.pointer_type)], |
29967ef6 XL |
14 | returns: vec![AbiParam::new(types::I32)], |
15 | }, | |
16 | ) | |
17 | .unwrap(); | |
17df50a5 | 18 | let puts = fx.module.declare_func_in_func(puts, &mut fx.bcx.func); |
cdc7bbd5 | 19 | if fx.clif_comments.enabled() { |
29967ef6 XL |
20 | fx.add_comment(puts, "puts"); |
21 | } | |
22 | ||
17df50a5 XL |
23 | let real_msg = format!("trap at {:?} ({}): {}\0", fx.instance, fx.symbol_name, msg); |
24 | let msg_ptr = fx.anonymous_str(&real_msg); | |
29967ef6 XL |
25 | fx.bcx.ins().call(puts, &[msg_ptr]); |
26 | } | |
27 | ||
28 | /// Trap code: user1 | |
6a06907d | 29 | pub(crate) fn trap_abort(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRef<str>) { |
29967ef6 XL |
30 | codegen_print(fx, msg.as_ref()); |
31 | fx.bcx.ins().trap(TrapCode::User(1)); | |
32 | } | |
33 | ||
34 | /// Use this for example when a function call should never return. This will fill the current block, | |
35 | /// so you can **not** add instructions to it afterwards. | |
36 | /// | |
37 | /// Trap code: user65535 | |
6a06907d | 38 | pub(crate) fn trap_unreachable(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRef<str>) { |
29967ef6 XL |
39 | codegen_print(fx, msg.as_ref()); |
40 | fx.bcx.ins().trap(TrapCode::UnreachableCodeReached); | |
41 | } | |
42 | ||
43 | /// Like `trap_unreachable` but returns a fake value of the specified type. | |
44 | /// | |
45 | /// Trap code: user65535 | |
46 | pub(crate) fn trap_unreachable_ret_value<'tcx>( | |
6a06907d | 47 | fx: &mut FunctionCx<'_, '_, 'tcx>, |
29967ef6 XL |
48 | dest_layout: TyAndLayout<'tcx>, |
49 | msg: impl AsRef<str>, | |
50 | ) -> CValue<'tcx> { | |
51 | codegen_print(fx, msg.as_ref()); | |
52 | let true_ = fx.bcx.ins().iconst(types::I32, 1); | |
53 | fx.bcx.ins().trapnz(true_, TrapCode::UnreachableCodeReached); | |
54 | CValue::by_ref(Pointer::const_addr(fx, 0), dest_layout) | |
55 | } | |
56 | ||
57 | /// Use this when something is unimplemented, but `libcore` or `libstd` requires it to codegen. | |
58 | /// Unlike `trap_unreachable` this will not fill the current block, so you **must** add instructions | |
59 | /// to it afterwards. | |
60 | /// | |
61 | /// Trap code: user65535 | |
6a06907d | 62 | pub(crate) fn trap_unimplemented(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRef<str>) { |
29967ef6 XL |
63 | codegen_print(fx, msg.as_ref()); |
64 | let true_ = fx.bcx.ins().iconst(types::I32, 1); | |
65 | fx.bcx.ins().trapnz(true_, TrapCode::User(!0)); | |
66 | } | |
fc512014 XL |
67 | |
68 | /// Like `trap_unimplemented` but returns a fake value of the specified type. | |
69 | /// | |
70 | /// Trap code: user65535 | |
71 | pub(crate) fn trap_unimplemented_ret_value<'tcx>( | |
6a06907d | 72 | fx: &mut FunctionCx<'_, '_, 'tcx>, |
fc512014 XL |
73 | dest_layout: TyAndLayout<'tcx>, |
74 | msg: impl AsRef<str>, | |
75 | ) -> CValue<'tcx> { | |
76 | trap_unimplemented(fx, msg); | |
77 | CValue::by_ref(Pointer::const_addr(fx, 0), dest_layout) | |
78 | } |