mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
roc_panic is passed a RocStr
This commit is contained in:
parent
a9f8c2ddec
commit
4709f9a0de
4 changed files with 41 additions and 38 deletions
|
@ -344,7 +344,7 @@ impl<'a, 'ctx, 'env> Env<'a, 'ctx, 'env> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn call_panic(&self, message: PointerValue<'ctx>, tag_id: PanicTagId) {
|
pub fn call_panic(&self, message: BasicValueEnum<'ctx>, tag_id: PanicTagId) {
|
||||||
let function = self.module.get_function("roc_panic").unwrap();
|
let function = self.module.get_function("roc_panic").unwrap();
|
||||||
let tag_id = self
|
let tag_id = self
|
||||||
.context
|
.context
|
||||||
|
@ -2626,7 +2626,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
roc_target::PtrWidth::Bytes4 => {
|
roc_target::PtrWidth::Bytes4 => {
|
||||||
// temporary WASM implementation
|
// temporary WASM implementation
|
||||||
throw_exception(env, "An expectation failed!");
|
throw_exception(env, parent, "An expectation failed!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2688,7 +2688,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
roc_target::PtrWidth::Bytes4 => {
|
roc_target::PtrWidth::Bytes4 => {
|
||||||
// temporary WASM implementation
|
// temporary WASM implementation
|
||||||
throw_exception(env, "An expectation failed!");
|
throw_exception(env, parent, "An expectation failed!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2709,7 +2709,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
|
|
||||||
RuntimeError(error_msg) => {
|
RuntimeError(error_msg) => {
|
||||||
throw_exception(env, error_msg);
|
throw_exception(env, parent, error_msg);
|
||||||
|
|
||||||
// unused value (must return a BasicValue)
|
// unused value (must return a BasicValue)
|
||||||
let zero = env.context.i64_type().const_zero();
|
let zero = env.context.i64_type().const_zero();
|
||||||
|
@ -3867,14 +3867,14 @@ pub fn build_setjmp_call<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> BasicValu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pointer to pointer of the panic message.
|
/// Pointer to RocStr which is the panic message.
|
||||||
pub fn get_panic_msg_ptr<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> PointerValue<'ctx> {
|
pub fn get_panic_msg_ptr<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>) -> PointerValue<'ctx> {
|
||||||
let ptr_to_u8_ptr = env.context.i8_type().ptr_type(AddressSpace::Generic);
|
let str_typ = zig_str_type(env);
|
||||||
|
|
||||||
let global_name = "roc_panic_msg_ptr";
|
let global_name = "roc_panic_msg_str";
|
||||||
let global = env.module.get_global(global_name).unwrap_or_else(|| {
|
let global = env.module.get_global(global_name).unwrap_or_else(|| {
|
||||||
let global = env.module.add_global(ptr_to_u8_ptr, None, global_name);
|
let global = env.module.add_global(str_typ, None, global_name);
|
||||||
global.set_initializer(&ptr_to_u8_ptr.const_zero());
|
global.set_initializer(&str_typ.const_zero());
|
||||||
global
|
global
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3927,12 +3927,10 @@ fn set_jump_and_catch_long_jump<'a, 'ctx, 'env>(
|
||||||
{
|
{
|
||||||
builder.position_at_end(catch_block);
|
builder.position_at_end(catch_block);
|
||||||
|
|
||||||
let error_msg = {
|
let error_msg_ptr = {
|
||||||
// u8**
|
// RocStr* global
|
||||||
let ptr_int_ptr = get_panic_msg_ptr(env);
|
let ptr_roc_str = get_panic_msg_ptr(env);
|
||||||
|
ptr_roc_str
|
||||||
// u8* again
|
|
||||||
builder.build_load(ptr_int_ptr, "ptr_int")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let return_value = {
|
let return_value = {
|
||||||
|
@ -3946,7 +3944,7 @@ fn set_jump_and_catch_long_jump<'a, 'ctx, 'env>(
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let v3 = builder
|
let v3 = builder
|
||||||
.build_insert_value(v2, error_msg, 1, "set_exception")
|
.build_insert_value(v2, error_msg_ptr, 1, "set_exception")
|
||||||
.unwrap();
|
.unwrap();
|
||||||
v3
|
v3
|
||||||
};
|
};
|
||||||
|
@ -5549,23 +5547,16 @@ fn define_global_error_str<'a, 'ctx, 'env>(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn throw_exception<'a, 'ctx, 'env>(env: &Env<'a, 'ctx, 'env>, message: &str) {
|
pub(crate) fn throw_exception<'a, 'ctx, 'env>(
|
||||||
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
|
parent: FunctionValue<'ctx>,
|
||||||
|
message: &str,
|
||||||
|
) {
|
||||||
let builder = env.builder;
|
let builder = env.builder;
|
||||||
|
|
||||||
// define the error message as a global
|
let str = build_string_literal(env, parent, message);
|
||||||
// (a hash is used such that the same value is not defined repeatedly)
|
|
||||||
let error_msg_global = define_global_error_str(env, message);
|
|
||||||
|
|
||||||
let cast = env
|
env.call_panic(str, PanicTagId::NullTerminatedString);
|
||||||
.builder
|
|
||||||
.build_bitcast(
|
|
||||||
error_msg_global.as_pointer_value(),
|
|
||||||
env.context.i8_type().ptr_type(AddressSpace::Generic),
|
|
||||||
"cast_void",
|
|
||||||
)
|
|
||||||
.into_pointer_value();
|
|
||||||
|
|
||||||
env.call_panic(cast, PanicTagId::NullTerminatedString);
|
|
||||||
|
|
||||||
builder.build_unreachable();
|
builder.build_unreachable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -193,7 +193,7 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {
|
||||||
// already been defined by the builtins, which rely on it.
|
// already been defined by the builtins, which rely on it.
|
||||||
let fn_val = module.get_function("roc_panic").unwrap();
|
let fn_val = module.get_function("roc_panic").unwrap();
|
||||||
let mut params = fn_val.get_param_iter();
|
let mut params = fn_val.get_param_iter();
|
||||||
let ptr_arg = params.next().unwrap();
|
let roc_str_arg = params.next().unwrap();
|
||||||
|
|
||||||
// in debug mode, this is assumed to be NullTerminatedString
|
// in debug mode, this is assumed to be NullTerminatedString
|
||||||
let _tag_id_arg = params.next().unwrap();
|
let _tag_id_arg = params.next().unwrap();
|
||||||
|
@ -210,8 +210,17 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {
|
||||||
|
|
||||||
builder.position_at_end(entry);
|
builder.position_at_end(entry);
|
||||||
|
|
||||||
// write our error message pointer
|
let loaded_roc_str = match env.target_info.ptr_width() {
|
||||||
env.builder.build_store(get_panic_msg_ptr(env), ptr_arg);
|
roc_target::PtrWidth::Bytes4 => roc_str_arg,
|
||||||
|
// On 64-bit we pass RocStrs by reference internally
|
||||||
|
roc_target::PtrWidth::Bytes8 => {
|
||||||
|
builder.build_load(roc_str_arg.into_pointer_value(), "load_roc_str")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// write our error message to the RocStr pointer
|
||||||
|
env.builder
|
||||||
|
.build_store(get_panic_msg_ptr(env), loaded_roc_str);
|
||||||
|
|
||||||
build_longjmp_call(env);
|
build_longjmp_call(env);
|
||||||
|
|
||||||
|
|
|
@ -1557,7 +1557,7 @@ fn throw_on_overflow<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
bd.position_at_end(throw_block);
|
bd.position_at_end(throw_block);
|
||||||
|
|
||||||
throw_exception(env, message);
|
throw_exception(env, parent, message);
|
||||||
|
|
||||||
bd.position_at_end(then_block);
|
bd.position_at_end(then_block);
|
||||||
|
|
||||||
|
@ -2005,6 +2005,7 @@ fn int_neg_raise_on_overflow<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
throw_exception(
|
throw_exception(
|
||||||
env,
|
env,
|
||||||
|
parent,
|
||||||
"integer negation overflowed because its argument is the minimum value",
|
"integer negation overflowed because its argument is the minimum value",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -2035,6 +2036,7 @@ fn int_abs_raise_on_overflow<'a, 'ctx, 'env>(
|
||||||
|
|
||||||
throw_exception(
|
throw_exception(
|
||||||
env,
|
env,
|
||||||
|
parent,
|
||||||
"integer absolute overflowed because its argument is the minimum value",
|
"integer absolute overflowed because its argument is the minimum value",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -2,13 +2,15 @@ use std::ffi::CStr;
|
||||||
use std::mem::MaybeUninit;
|
use std::mem::MaybeUninit;
|
||||||
use std::os::raw::c_char;
|
use std::os::raw::c_char;
|
||||||
|
|
||||||
|
use roc_std::RocStr;
|
||||||
|
|
||||||
/// This must have the same size as the repr() of RocCallResult!
|
/// This must have the same size as the repr() of RocCallResult!
|
||||||
pub const ROC_CALL_RESULT_DISCRIMINANT_SIZE: usize = std::mem::size_of::<u64>();
|
pub const ROC_CALL_RESULT_DISCRIMINANT_SIZE: usize = std::mem::size_of::<u64>();
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct RocCallResult<T> {
|
pub struct RocCallResult<T> {
|
||||||
tag: u64,
|
tag: u64,
|
||||||
error_msg: *mut c_char,
|
error_msg: *mut RocStr,
|
||||||
value: MaybeUninit<T>,
|
value: MaybeUninit<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,9 +39,8 @@ impl<T: Sized> From<RocCallResult<T>> for Result<T, String> {
|
||||||
match call_result.tag {
|
match call_result.tag {
|
||||||
0 => Ok(unsafe { call_result.value.assume_init() }),
|
0 => Ok(unsafe { call_result.value.assume_init() }),
|
||||||
_ => Err({
|
_ => Err({
|
||||||
let raw = unsafe { CStr::from_ptr(call_result.error_msg) };
|
let msg: &RocStr = unsafe { &*call_result.error_msg };
|
||||||
|
msg.as_str().to_owned()
|
||||||
raw.to_str().unwrap().to_owned()
|
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue