diff --git a/crates/compiler/gen_dev/src/generic64/mod.rs b/crates/compiler/gen_dev/src/generic64/mod.rs index e50a715a53..9e3aac1c00 100644 --- a/crates/compiler/gen_dev/src/generic64/mod.rs +++ b/crates/compiler/gen_dev/src/generic64/mod.rs @@ -919,6 +919,12 @@ impl< ASM::function_pointer(&mut self.buf, &mut self.relocs, fn_name, reg) } + fn build_data_pointer(&mut self, dst: &Symbol, data_name: String) { + let reg = self.storage_manager.claim_general_reg(&mut self.buf, dst); + + ASM::data_pointer(&mut self.buf, &mut self.relocs, data_name, reg) + } + fn build_fn_call( &mut self, dst: &Symbol, diff --git a/crates/compiler/gen_dev/src/lib.rs b/crates/compiler/gen_dev/src/lib.rs index 26e272610a..1eb1176498 100644 --- a/crates/compiler/gen_dev/src/lib.rs +++ b/crates/compiler/gen_dev/src/lib.rs @@ -1665,6 +1665,23 @@ trait Backend<'a> { arg_layouts, ret_layout, ), + LowLevel::SetJmp => self.build_fn_call( + sym, + String::from("roc_setjmp"), + args, + arg_layouts, + ret_layout, + ), + LowLevel::LongJmp => self.build_fn_call( + sym, + String::from("roc_longjmp"), + args, + arg_layouts, + ret_layout, + ), + LowLevel::SetLongJmpBuffer => { + self.build_data_pointer(sym, String::from("setlongjmp_buffer")) + } LowLevel::DictPseudoSeed => self.build_fn_call( sym, bitcode::UTILS_DICT_PSEUDO_SEED.to_string(), @@ -1967,6 +1984,7 @@ trait Backend<'a> { ); fn build_fn_pointer(&mut self, dst: &Symbol, fn_name: String); + fn build_data_pointer(&mut self, dst: &Symbol, data_name: String); /// Move a returned value into `dst` fn move_return_value(&mut self, dst: &Symbol, ret_layout: &InLayout<'a>); diff --git a/crates/compiler/gen_dev/src/object_builder.rs b/crates/compiler/gen_dev/src/object_builder.rs index 93b40cc2e8..01d70f20a3 100644 --- a/crates/compiler/gen_dev/src/object_builder.rs +++ b/crates/compiler/gen_dev/src/object_builder.rs @@ -142,7 +142,7 @@ fn generate_setlongjmp_buffer<'a, B: Backend<'a>>( dbg!(output.add_symbol(symbol)) } -fn generate_roc_setjmp<'a, B: Backend<'a>>(backend: &mut B, output: &mut Object) { +fn generate_roc_setlongjmp_buffer<'a, B: Backend<'a>>(backend: &mut B, output: &mut Object) { let text_section = output.section_id(StandardSection::Text); let proc_symbol = Symbol { name: b"roc_setjmp".to_vec(), @@ -160,6 +160,42 @@ fn generate_roc_setjmp<'a, B: Backend<'a>>(backend: &mut B, output: &mut Object) let proc_offset = output.add_symbol_data(proc_id, text_section, proc_data, 16); } +fn generate_setjmp<'a, B: Backend<'a>>(backend: &mut B, output: &mut Object) { + let text_section = output.section_id(StandardSection::Text); + let proc_symbol = Symbol { + name: b"roc_setjmp".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Text, + scope: SymbolScope::Dynamic, + weak: false, + section: SymbolSection::Section(text_section), + flags: SymbolFlags::None, + }; + let proc_id = output.add_symbol(proc_symbol); + let proc_data = backend.build_roc_setjmp(); + + output.add_symbol_data(proc_id, text_section, proc_data, 16); +} + +fn generate_longjmp<'a, B: Backend<'a>>(backend: &mut B, output: &mut Object) { + let text_section = output.section_id(StandardSection::Text); + let proc_symbol = Symbol { + name: b"roc_longjmp".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Text, + scope: SymbolScope::Dynamic, + weak: false, + section: SymbolSection::Section(text_section), + flags: SymbolFlags::None, + }; + let proc_id = output.add_symbol(proc_symbol); + let proc_data = backend.build_roc_longjmp(); + + output.add_symbol_data(proc_id, text_section, proc_data, 16); +} + fn generate_wrapper<'a, B: Backend<'a>>( backend: &mut B, output: &mut Object, @@ -234,7 +270,10 @@ fn build_object<'a, B: Backend<'a>>( ); */ - let setlongjmp_buffer = generate_setlongjmp_buffer(&mut backend, &mut output); + generate_setlongjmp_buffer(&mut backend, &mut output); + + generate_setjmp(&mut backend, &mut output); + generate_longjmp(&mut backend, &mut output); if backend.env().mode.generate_allocators() { generate_wrapper( @@ -576,6 +615,39 @@ fn build_exposed_generic_proc<'a, B: Backend<'a>>(backend: &mut B, proc: &Proc<' } } +fn build_test_main<'a, B: Backend<'a>>( + output: &mut Object<'a>, + layout_ids: &mut LayoutIds<'a>, + procs: &mut Vec<'a, (String, SectionId, SymbolId, Proc<'a>)>, + backend: &mut B, + layout: ProcLayout<'a>, + proc: Proc<'a>, + exposed: Exposed, +) { + let sym = proc.name.name(); + + let section_id = output.add_section( + output.segment_name(StandardSegment::Text).to_vec(), + &b".text.test_main", + SectionKind::Text, + ); + + let fn_name = "test_main"; + + let proc_symbol = Symbol { + name: fn_name.as_bytes().to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Text, + scope: SymbolScope::Linkage, + weak: false, + section: SymbolSection::Section(section_id), + flags: SymbolFlags::None, + }; + let proc_id = output.add_symbol(proc_symbol); + procs.push((fn_name, section_id, proc_id, proc)); +} + #[allow(clippy::enum_variant_names)] enum Exposed { ExposedGeneric, diff --git a/crates/compiler/mono/src/code_gen_help/mod.rs b/crates/compiler/mono/src/code_gen_help/mod.rs index 861aaec471..c266787194 100644 --- a/crates/compiler/mono/src/code_gen_help/mod.rs +++ b/crates/compiler/mono/src/code_gen_help/mod.rs @@ -6,8 +6,8 @@ use roc_module::symbol::{IdentIds, ModuleId, Symbol}; use roc_target::TargetInfo; use crate::ir::{ - Call, CallSpecId, CallType, Expr, HostExposedLayouts, JoinPointId, ModifyRc, PassedFunction, - Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId, + Call, CallSpecId, CallType, Expr, HostExposedLayouts, JoinPointId, Literal, ModifyRc, + PassedFunction, Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId, }; use crate::layout::{ Builtin, InLayout, LambdaName, Layout, LayoutInterner, LayoutRepr, LayoutWrapper, Niche, @@ -848,3 +848,93 @@ fn layout_needs_helper_proc<'a>( LayoutRepr::Erased(_) => true, } } + +fn test_helper<'a>( + arena: &'a Bump, + layout_interner: &STLayoutInterner<'a>, + main_proc: &Proc<'a>, +) -> Proc<'a> { + Proc { + name: (), + args: (), + body: (), + closure_data_layout: (), + ret_layout: (), + is_self_recursive: (), + host_exposed_layouts: (), + is_erased: (), + } +} + +fn test_helper_body<'a>( + env: &CodeGenHelp, + ident_ids: &mut IdentIds, + layout_interner: &STLayoutInterner<'a>, + main_proc: &Proc<'a>, +) -> Stmt<'a> { + // let buffer = SetLongJmpBuffer + let buffer_symbol = env.create_symbol(ident_ids, "buffer"); + let buffer_expr = Expr::Call(Call { + call_type: CallType::LowLevel { + op: LowLevel::SetLongJmpBuffer, + update_mode: UpdateModeId::BACKEND_DUMMY, + }, + arguments: &[], + }); + let buffer_stmt = |next| Stmt::Let(buffer_symbol, buffer_expr, Layout::U64, next); + + let is_longjmp_symbol = env.create_symbol(ident_ids, "is_longjmp"); + let is_longjmp_expr = Expr::Call(Call { + call_type: CallType::LowLevel { + op: LowLevel::SetJmp, + update_mode: UpdateModeId::BACKEND_DUMMY, + }, + arguments: &[buffer_symbol], + }); + let is_longjmp_stmt = |next| Stmt::Let(is_longjmp_symbol, is_longjmp_expr, Layout::U64, next); + + // tag: u64, + // error_msg: *mut RocStr, + // value: MaybeUninit, + let repr = + LayoutRepr::Struct( + env.arena + .alloc([Layout::U64, Layout::U64, main_proc.ret_layout]), + ); + let return_layout = layout_interner.insert_direct_no_semantic(repr); + + // normal path, no panics + let else_branch_stmt = { + let result_symbol = Expr::Call(Call { + call_type: CallType::ByName { + name: (), + ret_layout: (), + arg_layouts: (), + specialization_id: (), + }, + arguments: proc_arguments, + }); + + let ok_tag_symbol = env.create_symbol(ident_ids, "ok_tag"); + let ok_tag_expr = Expr::Literal(Literal::Int((0 as i128).to_be_bytes())); + let ok_tag = |next| Stmt::Let(ok_tag_symbol, ok_tag_expr, Layout::U64, next); + + let msg_ptr_symbol = env.create_symbol(ident_ids, "msg_ptr"); + let msg_ptr_expr = Expr::Literal(Literal::Int((0 as i128).to_be_bytes())); + let msg_ptr = |next| Stmt::Let(msg_ptr_symbol, msg_ptr_expr, Layout::U64, next); + }; + + // a longjmp/panic occured + let then_branch_stmt = { + // + todo!() + }; + + Stmt::if_then_else( + env.arena, + is_longjmp_symbol, + return_layout, + then_branch_stmt, + else_branch_stmt, + ) +} diff --git a/crates/compiler/test_gen/src/helpers/dev.rs b/crates/compiler/test_gen/src/helpers/dev.rs index fd94e6e87f..3cbb4324e2 100644 --- a/crates/compiler/test_gen/src/helpers/dev.rs +++ b/crates/compiler/test_gen/src/helpers/dev.rs @@ -212,7 +212,7 @@ pub fn helper( let builtins_host_tempfile = roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile"); - if false { + if true { std::fs::copy(&app_o_file, "/tmp/app.o").unwrap(); }