roc_panic is passed a RocStr

This commit is contained in:
Ayaz Hafiz 2022-11-22 14:03:04 -06:00
parent a9f8c2ddec
commit 4709f9a0de
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
4 changed files with 41 additions and 38 deletions

View file

@ -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();
} }

View file

@ -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);

View file

@ -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",
); );

View file

@ -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()
}), }),
} }
} }