Call panic lang item on failed TerminatorKind::Assert

Fixes #164
This commit is contained in:
bjorn3 2020-04-25 19:07:25 +02:00
parent 7dbbfe668f
commit 7031c96fb3
7 changed files with 79 additions and 43 deletions

View file

@ -13,7 +13,7 @@ use mini_core::*;
macro_rules! assert_eq {
($l:expr, $r: expr) => {
if $l != $r {
panic(&(stringify!($l != $r), file!(), line!(), 0));
panic(stringify!($l != $r));
}
}
}

View file

@ -1,7 +1,7 @@
#![feature(
no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types,
untagged_unions, decl_macro, rustc_attrs, transparent_unions, optin_builtin_traits,
thread_local,
thread_local, track_caller
)]
#![no_core]
#![allow(dead_code)]
@ -394,9 +394,19 @@ pub trait FnMut<Args>: FnOnce<Args> {
}
#[lang = "panic"]
pub fn panic(&(_msg, _file, _line, _col): &(&'static str, &'static str, u32, u32)) -> ! {
#[track_caller]
pub fn panic(msg: &str) -> ! {
unsafe {
libc::puts("Panicking\0" as *const str as *const u8);
libc::puts("Panicking\n\0" as *const str as *const u8);
intrinsics::abort();
}
}
#[lang = "panic_bounds_check"]
#[track_caller]
fn panic_bounds_check(index: usize, len: usize) -> ! {
unsafe {
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);
intrinsics::abort();
}
}

View file

@ -97,7 +97,7 @@ static NUM_REF: &'static u8 = unsafe { &NUM };
macro_rules! assert {
($e:expr) => {
if !$e {
panic(&(stringify!(! $e), file!(), line!(), 0));
panic(stringify!(! $e));
}
};
}
@ -105,7 +105,7 @@ macro_rules! assert {
macro_rules! assert_eq {
($l:expr, $r: expr) => {
if $l != $r {
panic(&(stringify!($l != $r), file!(), line!(), 0));
panic(stringify!($l != $r));
}
}
}

View file

@ -206,7 +206,7 @@ impl<'tcx, B: Backend + 'static> FunctionCx<'_, 'tcx, B> {
func_ref
}
fn lib_call(
pub(crate) fn lib_call(
&mut self,
name: &str,
input_tys: Vec<types::Type>,

View file

@ -241,14 +241,36 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, impl Backend>) {
fx.bcx.ins().jump(target, &[]);
fx.bcx.switch_to_block(failure);
trap_panic(
fx,
format!(
"[panic] Assert {:?} at {:?} failed.",
msg,
bb_data.terminator().source_info.span
),
);
let location = fx.get_caller_location(bb_data.terminator().source_info.span).load_scalar(fx);
let args;
let lang_item = match msg {
AssertKind::BoundsCheck { ref len, ref index } => {
let len = trans_operand(fx, len).load_scalar(fx);
let index = trans_operand(fx, index).load_scalar(fx);
args = [index, len, location];
rustc_hir::lang_items::PanicBoundsCheckFnLangItem
}
_ => {
let msg_str = msg.description();
let msg_ptr = fx.anonymous_str("assert", msg_str);
let msg_len = fx.bcx.ins().iconst(fx.pointer_type, i64::try_from(msg_str.len()).unwrap());
args = [msg_ptr, msg_len, location];
rustc_hir::lang_items::PanicFnLangItem
}
};
let def_id = fx.tcx.lang_items().require(lang_item).unwrap_or_else(|s| {
fx.tcx.sess.span_fatal(bb_data.terminator().source_info.span, &s)
});
let instance = Instance::mono(fx.tcx, def_id);
let symbol_name = fx.tcx.symbol_name(instance).name.as_str();
fx.lib_call(&*symbol_name, vec![fx.pointer_type, fx.pointer_type, fx.pointer_type], vec![], &args);
crate::trap::trap_unreachable(fx, "panic lang item returned");
}
TerminatorKind::SwitchInt {

View file

@ -410,4 +410,35 @@ impl<'tcx, B: Backend + 'static> FunctionCx<'_, 'tcx, B> {
pub(crate) fn triple(&self) -> &target_lexicon::Triple {
self.module.isa().triple()
}
pub(crate) fn anonymous_str(&mut self, prefix: &str, msg: &str) -> Value {
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
let mut hasher = DefaultHasher::new();
msg.hash(&mut hasher);
let msg_hash = hasher.finish();
let mut data_ctx = DataContext::new();
data_ctx.define(msg.as_bytes().to_vec().into_boxed_slice());
let msg_id = self
.module
.declare_data(
&format!("__{}_{:08x}", prefix, msg_hash),
Linkage::Local,
false,
false,
None,
)
.unwrap();
// Ignore DuplicateDefinition error, as the data will be the same
let _ = self.module.define_data(msg_id, &data_ctx);
let local_msg_id = self.module.declare_data_in_func(msg_id, self.bcx.func);
#[cfg(debug_assertions)]
{
self.add_comment(local_msg_id, msg);
}
self.bcx.ins().global_value(self.pointer_type, local_msg_id)
}
}

View file

@ -1,6 +1,3 @@
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use crate::prelude::*;
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
let symbol_name = fx.tcx.symbol_name(fx.instance);
let real_msg = format!("trap at {:?} ({}): {}\0", fx.instance, symbol_name, msg);
let mut hasher = DefaultHasher::new();
real_msg.hash(&mut hasher);
let msg_hash = hasher.finish();
let mut data_ctx = DataContext::new();
data_ctx.define(real_msg.as_bytes().to_vec().into_boxed_slice());
let msg_id = fx
.module
.declare_data(
&format!("__trap_{:08x}", msg_hash),
Linkage::Local,
false,
false,
None,
)
.unwrap();
// Ignore DuplicateDefinition error, as the data will be the same
let _ = fx.module.define_data(msg_id, &data_ctx);
let local_msg_id = fx.module.declare_data_in_func(msg_id, fx.bcx.func);
#[cfg(debug_assertions)]
{
fx.add_comment(local_msg_id, msg);
}
let msg_ptr = fx.bcx.ins().global_value(pointer_ty(fx.tcx), local_msg_id);
let msg_ptr = fx.anonymous_str("trap", &real_msg);
fx.bcx.ins().call(puts, &[msg_ptr]);
}