Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 7031c96

Browse files
committed
Call panic lang item on failed TerminatorKind::Assert
Fixes rust-lang#164
1 parent 7dbbfe6 commit 7031c96

File tree

7 files changed

+79
-43
lines changed

7 files changed

+79
-43
lines changed

example/arbitrary_self_types_pointers_and_wrappers.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use mini_core::*;
1313
macro_rules! assert_eq {
1414
($l:expr, $r: expr) => {
1515
if $l != $r {
16-
panic(&(stringify!($l != $r), file!(), line!(), 0));
16+
panic(stringify!($l != $r));
1717
}
1818
}
1919
}

example/mini_core.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![feature(
22
no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types,
33
untagged_unions, decl_macro, rustc_attrs, transparent_unions, optin_builtin_traits,
4-
thread_local,
4+
thread_local, track_caller
55
)]
66
#![no_core]
77
#![allow(dead_code)]
@@ -394,9 +394,19 @@ pub trait FnMut<Args>: FnOnce<Args> {
394394
}
395395

396396
#[lang = "panic"]
397-
pub fn panic(&(_msg, _file, _line, _col): &(&'static str, &'static str, u32, u32)) -> ! {
397+
#[track_caller]
398+
pub fn panic(msg: &str) -> ! {
398399
unsafe {
399-
libc::puts("Panicking\0" as *const str as *const u8);
400+
libc::puts("Panicking\n\0" as *const str as *const u8);
401+
intrinsics::abort();
402+
}
403+
}
404+
405+
#[lang = "panic_bounds_check"]
406+
#[track_caller]
407+
fn panic_bounds_check(index: usize, len: usize) -> ! {
408+
unsafe {
409+
libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index);
400410
intrinsics::abort();
401411
}
402412
}

example/mini_core_hello_world.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,15 @@ static NUM_REF: &'static u8 = unsafe { &NUM };
9797
macro_rules! assert {
9898
($e:expr) => {
9999
if !$e {
100-
panic(&(stringify!(! $e), file!(), line!(), 0));
100+
panic(stringify!(! $e));
101101
}
102102
};
103103
}
104104

105105
macro_rules! assert_eq {
106106
($l:expr, $r: expr) => {
107107
if $l != $r {
108-
panic(&(stringify!($l != $r), file!(), line!(), 0));
108+
panic(stringify!($l != $r));
109109
}
110110
}
111111
}

src/abi/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ impl<'tcx, B: Backend + 'static> FunctionCx<'_, 'tcx, B> {
206206
func_ref
207207
}
208208

209-
fn lib_call(
209+
pub(crate) fn lib_call(
210210
&mut self,
211211
name: &str,
212212
input_tys: Vec<types::Type>,

src/base.rs

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -241,14 +241,36 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, impl Backend>) {
241241
fx.bcx.ins().jump(target, &[]);
242242

243243
fx.bcx.switch_to_block(failure);
244-
trap_panic(
245-
fx,
246-
format!(
247-
"[panic] Assert {:?} at {:?} failed.",
248-
msg,
249-
bb_data.terminator().source_info.span
250-
),
251-
);
244+
245+
let location = fx.get_caller_location(bb_data.terminator().source_info.span).load_scalar(fx);
246+
247+
let args;
248+
let lang_item = match msg {
249+
AssertKind::BoundsCheck { ref len, ref index } => {
250+
let len = trans_operand(fx, len).load_scalar(fx);
251+
let index = trans_operand(fx, index).load_scalar(fx);
252+
args = [index, len, location];
253+
rustc_hir::lang_items::PanicBoundsCheckFnLangItem
254+
}
255+
_ => {
256+
let msg_str = msg.description();
257+
let msg_ptr = fx.anonymous_str("assert", msg_str);
258+
let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
259+
args = [msg_ptr, msg_len, location];
260+
rustc_hir::lang_items::PanicFnLangItem
261+
}
262+
};
263+
264+
let def_id = fx.tcx.lang_items().require(lang_item).unwrap_or_else(|s| {
265+
fx.tcx.sess.span_fatal(bb_data.terminator().source_info.span, &s)
266+
});
267+
268+
let instance = Instance::mono(fx.tcx, def_id);
269+
let symbol_name = fx.tcx.symbol_name(instance).name.as_str();
270+
271+
fx.lib_call(&*symbol_name, vec![fx.pointer_type, fx.pointer_type, fx.pointer_type], vec![], &args);
272+
273+
crate::trap::trap_unreachable(fx, "panic lang item returned");
252274
}
253275

254276
TerminatorKind::SwitchInt {

src/common.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,4 +410,35 @@ impl<'tcx, B: Backend + 'static> FunctionCx<'_, 'tcx, B> {
410410
pub(crate) fn triple(&self) -> &target_lexicon::Triple {
411411
self.module.isa().triple()
412412
}
413+
414+
pub(crate) fn anonymous_str(&mut self, prefix: &str, msg: &str) -> Value {
415+
use std::collections::hash_map::DefaultHasher;
416+
use std::hash::{Hash, Hasher};
417+
418+
let mut hasher = DefaultHasher::new();
419+
msg.hash(&mut hasher);
420+
let msg_hash = hasher.finish();
421+
let mut data_ctx = DataContext::new();
422+
data_ctx.define(msg.as_bytes().to_vec().into_boxed_slice());
423+
let msg_id = self
424+
.module
425+
.declare_data(
426+
&format!("__{}_{:08x}", prefix, msg_hash),
427+
Linkage::Local,
428+
false,
429+
false,
430+
None,
431+
)
432+
.unwrap();
433+
434+
// Ignore DuplicateDefinition error, as the data will be the same
435+
let _ = self.module.define_data(msg_id, &data_ctx);
436+
437+
let local_msg_id = self.module.declare_data_in_func(msg_id, self.bcx.func);
438+
#[cfg(debug_assertions)]
439+
{
440+
self.add_comment(local_msg_id, msg);
441+
}
442+
self.bcx.ins().global_value(self.pointer_type, local_msg_id)
443+
}
413444
}

src/trap.rs

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
use std::collections::hash_map::DefaultHasher;
2-
use std::hash::{Hash, Hasher};
3-
41
use crate::prelude::*;
52

63
fn codegen_print(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: &str) {
@@ -24,31 +21,7 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, ms
2421

2522
let symbol_name = fx.tcx.symbol_name(fx.instance);
2623
let real_msg = format!("trap at {:?} ({}): {}\0", fx.instance, symbol_name, msg);
27-
let mut hasher = DefaultHasher::new();
28-
real_msg.hash(&mut hasher);
29-
let msg_hash = hasher.finish();
30-
let mut data_ctx = DataContext::new();
31-
data_ctx.define(real_msg.as_bytes().to_vec().into_boxed_slice());
32-
let msg_id = fx
33-
.module
34-
.declare_data(
35-
&format!("__trap_{:08x}", msg_hash),
36-
Linkage::Local,
37-
false,
38-
false,
39-
None,
40-
)
41-
.unwrap();
42-
43-
// Ignore DuplicateDefinition error, as the data will be the same
44-
let _ = fx.module.define_data(msg_id, &data_ctx);
45-
46-
let local_msg_id = fx.module.declare_data_in_func(msg_id, fx.bcx.func);
47-
#[cfg(debug_assertions)]
48-
{
49-
fx.add_comment(local_msg_id, msg);
50-
}
51-
let msg_ptr = fx.bcx.ins().global_value(pointer_ty(fx.tcx), local_msg_id);
24+
let msg_ptr = fx.anonymous_str("trap", &real_msg);
5225
fx.bcx.ins().call(puts, &[msg_ptr]);
5326
}
5427

0 commit comments

Comments
 (0)