mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-25 04:52:32 +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 tag_id = self
|
||||
.context
|
||||
|
@ -2626,7 +2626,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
|||
}
|
||||
roc_target::PtrWidth::Bytes4 => {
|
||||
// temporary WASM implementation
|
||||
throw_exception(env, "An expectation failed!");
|
||||
throw_exception(env, parent, "An expectation failed!");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2688,7 +2688,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
|||
}
|
||||
roc_target::PtrWidth::Bytes4 => {
|
||||
// temporary WASM implementation
|
||||
throw_exception(env, "An expectation failed!");
|
||||
throw_exception(env, parent, "An expectation failed!");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -2709,7 +2709,7 @@ pub fn build_exp_stmt<'a, 'ctx, 'env>(
|
|||
}
|
||||
|
||||
RuntimeError(error_msg) => {
|
||||
throw_exception(env, error_msg);
|
||||
throw_exception(env, parent, error_msg);
|
||||
|
||||
// unused value (must return a BasicValue)
|
||||
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> {
|
||||
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.add_global(ptr_to_u8_ptr, None, global_name);
|
||||
global.set_initializer(&ptr_to_u8_ptr.const_zero());
|
||||
let global = env.module.add_global(str_typ, None, global_name);
|
||||
global.set_initializer(&str_typ.const_zero());
|
||||
global
|
||||
});
|
||||
|
||||
|
@ -3927,12 +3927,10 @@ fn set_jump_and_catch_long_jump<'a, 'ctx, 'env>(
|
|||
{
|
||||
builder.position_at_end(catch_block);
|
||||
|
||||
let error_msg = {
|
||||
// u8**
|
||||
let ptr_int_ptr = get_panic_msg_ptr(env);
|
||||
|
||||
// u8* again
|
||||
builder.build_load(ptr_int_ptr, "ptr_int")
|
||||
let error_msg_ptr = {
|
||||
// RocStr* global
|
||||
let ptr_roc_str = get_panic_msg_ptr(env);
|
||||
ptr_roc_str
|
||||
};
|
||||
|
||||
let return_value = {
|
||||
|
@ -3946,7 +3944,7 @@ fn set_jump_and_catch_long_jump<'a, 'ctx, 'env>(
|
|||
.unwrap();
|
||||
|
||||
let v3 = builder
|
||||
.build_insert_value(v2, error_msg, 1, "set_exception")
|
||||
.build_insert_value(v2, error_msg_ptr, 1, "set_exception")
|
||||
.unwrap();
|
||||
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;
|
||||
|
||||
// define the error message as a global
|
||||
// (a hash is used such that the same value is not defined repeatedly)
|
||||
let error_msg_global = define_global_error_str(env, message);
|
||||
let str = build_string_literal(env, parent, message);
|
||||
|
||||
let cast = env
|
||||
.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);
|
||||
env.call_panic(str, PanicTagId::NullTerminatedString);
|
||||
|
||||
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.
|
||||
let fn_val = module.get_function("roc_panic").unwrap();
|
||||
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
|
||||
let _tag_id_arg = params.next().unwrap();
|
||||
|
@ -210,8 +210,17 @@ pub fn add_sjlj_roc_panic(env: &Env<'_, '_, '_>) {
|
|||
|
||||
builder.position_at_end(entry);
|
||||
|
||||
// write our error message pointer
|
||||
env.builder.build_store(get_panic_msg_ptr(env), ptr_arg);
|
||||
let loaded_roc_str = match env.target_info.ptr_width() {
|
||||
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);
|
||||
|
||||
|
|
|
@ -1557,7 +1557,7 @@ fn throw_on_overflow<'a, 'ctx, 'env>(
|
|||
|
||||
bd.position_at_end(throw_block);
|
||||
|
||||
throw_exception(env, message);
|
||||
throw_exception(env, parent, message);
|
||||
|
||||
bd.position_at_end(then_block);
|
||||
|
||||
|
@ -2005,6 +2005,7 @@ fn int_neg_raise_on_overflow<'a, 'ctx, 'env>(
|
|||
|
||||
throw_exception(
|
||||
env,
|
||||
parent,
|
||||
"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(
|
||||
env,
|
||||
parent,
|
||||
"integer absolute overflowed because its argument is the minimum value",
|
||||
);
|
||||
|
||||
|
|
|
@ -2,13 +2,15 @@ use std::ffi::CStr;
|
|||
use std::mem::MaybeUninit;
|
||||
use std::os::raw::c_char;
|
||||
|
||||
use roc_std::RocStr;
|
||||
|
||||
/// This must have the same size as the repr() of RocCallResult!
|
||||
pub const ROC_CALL_RESULT_DISCRIMINANT_SIZE: usize = std::mem::size_of::<u64>();
|
||||
|
||||
#[repr(C)]
|
||||
pub struct RocCallResult<T> {
|
||||
tag: u64,
|
||||
error_msg: *mut c_char,
|
||||
error_msg: *mut RocStr,
|
||||
value: MaybeUninit<T>,
|
||||
}
|
||||
|
||||
|
@ -37,9 +39,8 @@ impl<T: Sized> From<RocCallResult<T>> for Result<T, String> {
|
|||
match call_result.tag {
|
||||
0 => Ok(unsafe { call_result.value.assume_init() }),
|
||||
_ => Err({
|
||||
let raw = unsafe { CStr::from_ptr(call_result.error_msg) };
|
||||
|
||||
raw.to_str().unwrap().to_owned()
|
||||
let msg: &RocStr = unsafe { &*call_result.error_msg };
|
||||
msg.as_str().to_owned()
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue