mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-04 12:18:19 +00:00
so close
This commit is contained in:
parent
644def72f1
commit
f59eed6366
8 changed files with 107 additions and 33 deletions
|
@ -725,6 +725,9 @@ impl<
|
|||
fn interner(&self) -> &STLayoutInterner<'a> {
|
||||
self.layout_interner
|
||||
}
|
||||
fn relocations_mut(&mut self) -> &mut Vec<'a, Relocation> {
|
||||
&mut self.relocs
|
||||
}
|
||||
fn module_interns_helpers_mut(
|
||||
&mut self,
|
||||
) -> (
|
||||
|
@ -914,14 +917,16 @@ impl<
|
|||
out.into_bump_slice()
|
||||
}
|
||||
|
||||
fn build_roc_panic(&mut self) -> &'a [u8] {
|
||||
fn build_roc_panic(&mut self) -> (&'a [u8], Vec<'a, Relocation>) {
|
||||
let mut out = bumpalo::vec![in self.env.arena];
|
||||
|
||||
let before = self.relocs.len();
|
||||
|
||||
CC::roc_panic(&mut out, &mut self.relocs);
|
||||
|
||||
dbg!(&self.relocs);
|
||||
let relocs = self.relocs.split_off(before);
|
||||
|
||||
out.into_bump_slice()
|
||||
(out.into_bump_slice(), relocs)
|
||||
}
|
||||
|
||||
fn build_fn_pointer(&mut self, dst: &Symbol, fn_name: String) {
|
||||
|
@ -4262,7 +4267,18 @@ impl<
|
|||
Builtin::Int(int_width) => match int_width {
|
||||
IntWidth::I128 | IntWidth::U128 => {
|
||||
// can we treat this as 2 u64's?
|
||||
todo!()
|
||||
storage_manager.with_tmp_general_reg(
|
||||
buf,
|
||||
|storage_manager, buf, tmp_reg| {
|
||||
let base_offset = storage_manager.claim_stack_area(&dst, 16);
|
||||
|
||||
ASM::mov_reg64_mem64_offset32(buf, tmp_reg, ptr_reg, offset);
|
||||
ASM::mov_base32_reg64(buf, base_offset, tmp_reg);
|
||||
|
||||
ASM::mov_reg64_mem64_offset32(buf, tmp_reg, ptr_reg, offset + 8);
|
||||
ASM::mov_base32_reg64(buf, base_offset + 8, tmp_reg);
|
||||
},
|
||||
);
|
||||
}
|
||||
IntWidth::I64 | IntWidth::U64 => {
|
||||
let dst_reg = storage_manager.claim_general_reg(buf, &dst);
|
||||
|
@ -4300,6 +4316,15 @@ impl<
|
|||
}
|
||||
Builtin::Decimal => {
|
||||
// same as 128-bit integer
|
||||
storage_manager.with_tmp_general_reg(buf, |storage_manager, buf, tmp_reg| {
|
||||
let base_offset = storage_manager.claim_stack_area(&dst, 16);
|
||||
|
||||
ASM::mov_reg64_mem64_offset32(buf, tmp_reg, ptr_reg, offset);
|
||||
ASM::mov_base32_reg64(buf, base_offset, tmp_reg);
|
||||
|
||||
ASM::mov_reg64_mem64_offset32(buf, tmp_reg, ptr_reg, offset + 8);
|
||||
ASM::mov_base32_reg64(buf, base_offset + 8, tmp_reg);
|
||||
});
|
||||
}
|
||||
Builtin::Str | Builtin::List(_) => {
|
||||
storage_manager.with_tmp_general_reg(buf, |storage_manager, buf, tmp_reg| {
|
||||
|
|
|
@ -808,8 +808,15 @@ impl<
|
|||
}
|
||||
}
|
||||
}
|
||||
Builtin::Decimal => todo!(),
|
||||
Builtin::Decimal => {
|
||||
let (from_offset, size) = self.stack_offset_and_size(sym);
|
||||
debug_assert_eq!(from_offset % 8, 0);
|
||||
debug_assert_eq!(size % 8, 0);
|
||||
debug_assert_eq!(size, layout_interner.stack_size(*layout));
|
||||
self.copy_to_stack_offset(buf, size, from_offset, to_offset)
|
||||
}
|
||||
Builtin::Str | Builtin::List(_) => {
|
||||
dbg!(sym);
|
||||
let (from_offset, size) = self.stack_offset_and_size(sym);
|
||||
debug_assert_eq!(size, layout_interner.stack_size(*layout));
|
||||
self.copy_to_stack_offset(buf, size, from_offset, to_offset)
|
||||
|
|
|
@ -482,7 +482,8 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
offset += 8;
|
||||
|
||||
// store the current stack pointer
|
||||
ASM::mov_mem64_offset32_reg64(buf, RDI, offset, RSP);
|
||||
ASM::mov_reg64_mem64_offset32(buf, RDX, RSP, 0);
|
||||
ASM::mov_mem64_offset32_reg64(buf, RDI, offset, RDX);
|
||||
|
||||
// zero out eax, so we return 0i32 (we do a 64-bit xor for convenience)
|
||||
ASM::xor_reg64_reg64_reg64(buf, RAX, RAX, RAX);
|
||||
|
@ -507,7 +508,7 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
// 20237a: ff 67 38 jmp QWORD PTR [rdi+0x38]
|
||||
|
||||
// make sure something nonzero is returned ?!
|
||||
ASM::mov_reg64_imm64(buf, RAX, 0x1);
|
||||
ASM::mov_reg64_reg64(buf, RAX, RSI);
|
||||
|
||||
// move the values back into the registers
|
||||
let mut offset = 0;
|
||||
|
@ -525,11 +526,25 @@ impl CallConv<X86_64GeneralReg, X86_64FloatReg, X86_64Assembler> for X86_64Syste
|
|||
use X86_64GeneralReg::*;
|
||||
type ASM = X86_64Assembler;
|
||||
|
||||
ASM::data_pointer(buf, relocs, String::from("setlongjmp_buffer"), RDI);
|
||||
ASM::mov_reg64_imm64(buf, RSI, 42);
|
||||
// move the first argument to roc_panic (a *RocStr) into r8
|
||||
ASM::mov_reg64_imm64(buf, R8, 8);
|
||||
ASM::add_reg64_reg64_reg64(buf, R8, R8, RSP);
|
||||
|
||||
// Call function and generate reloc.
|
||||
ASM::call(buf, relocs, String::from("roc_longjmp"));
|
||||
// the setlongjmp_buffer
|
||||
ASM::data_pointer(buf, relocs, String::from("setlongjmp_buffer"), RDI);
|
||||
ASM::mov_reg64_mem64_offset32(buf, RDI, RDI, 0);
|
||||
|
||||
// the value to return from the longjmp. It is a pointer to the last 3 words of the setlongjmp_buffer
|
||||
// they represent the errore message.
|
||||
ASM::mov_reg64_imm64(buf, RSI, 0x40);
|
||||
ASM::add_reg64_reg64_reg64(buf, RSI, RSI, RDI);
|
||||
|
||||
for offset in [0, 8, 16] {
|
||||
ASM::mov_reg64_mem64_offset32(buf, R9, R8, offset);
|
||||
ASM::mov_mem64_offset32_reg64(buf, RSI, offset, R9);
|
||||
}
|
||||
|
||||
Self::longjmp(buf, relocs)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -291,6 +291,7 @@ trait Backend<'a> {
|
|||
fn interns(&self) -> &Interns;
|
||||
fn interns_mut(&mut self) -> &mut Interns;
|
||||
fn interner(&self) -> &STLayoutInterner<'a>;
|
||||
fn relocations_mut(&mut self) -> &mut Vec<'a, Relocation>;
|
||||
|
||||
fn interner_mut(&mut self) -> &mut STLayoutInterner<'a> {
|
||||
self.module_interns_helpers_mut().1
|
||||
|
@ -466,7 +467,7 @@ trait Backend<'a> {
|
|||
// use for roc_panic
|
||||
fn build_roc_setjmp(&mut self) -> &'a [u8];
|
||||
fn build_roc_longjmp(&mut self) -> &'a [u8];
|
||||
fn build_roc_panic(&mut self) -> &'a [u8];
|
||||
fn build_roc_panic(&mut self) -> (&'a [u8], Vec<'a, Relocation>);
|
||||
|
||||
/// build_proc creates a procedure and outputs it to the wrapped object writer.
|
||||
/// Returns the procedure bytes, its relocations, and the names of the refcounting functions it references.
|
||||
|
|
|
@ -121,10 +121,13 @@ pub fn build_module<'a, 'r>(
|
|||
fn define_setlongjmp_buffer(output: &mut Object) -> SymbolId {
|
||||
let bss_section = output.section_id(StandardSection::Data);
|
||||
|
||||
// 8 registers + 3 words for a RocStr
|
||||
const SIZE: usize = (8 + 3) * core::mem::size_of::<u64>();
|
||||
|
||||
let symbol = Symbol {
|
||||
name: b"setlongjmp_buffer".to_vec(),
|
||||
value: 0,
|
||||
size: 8 * core::mem::size_of::<u64>() as u64,
|
||||
size: SIZE as u64,
|
||||
kind: SymbolKind::Data,
|
||||
scope: SymbolScope::Dynamic,
|
||||
weak: false,
|
||||
|
@ -133,7 +136,7 @@ fn define_setlongjmp_buffer(output: &mut Object) -> SymbolId {
|
|||
};
|
||||
|
||||
let symbol_id = output.add_symbol(symbol);
|
||||
output.add_symbol_data(symbol_id, bss_section, &[0xAA; 64], 8);
|
||||
output.add_symbol_data(symbol_id, bss_section, &[0x00; SIZE], 8);
|
||||
|
||||
symbol_id
|
||||
}
|
||||
|
@ -188,9 +191,33 @@ fn generate_roc_panic<'a, B: Backend<'a>>(backend: &mut B, output: &mut Object)
|
|||
flags: SymbolFlags::None,
|
||||
};
|
||||
let proc_id = output.add_symbol(proc_symbol);
|
||||
let proc_data = backend.build_roc_panic();
|
||||
let (proc_data, relocs) = backend.build_roc_panic();
|
||||
|
||||
output.add_symbol_data(proc_id, text_section, proc_data, 16);
|
||||
let proc_offset = output.add_symbol_data(proc_id, text_section, proc_data, 16);
|
||||
|
||||
for r in relocs {
|
||||
let relocation = match r {
|
||||
Relocation::LocalData { offset, .. } => unreachable!(),
|
||||
Relocation::LinkedFunction { offset, .. } => unreachable!(),
|
||||
Relocation::LinkedData { offset, name } => {
|
||||
if let Some(sym_id) = output.symbol_id(name.as_bytes()) {
|
||||
write::Relocation {
|
||||
offset: offset + proc_offset,
|
||||
size: 32,
|
||||
kind: RelocationKind::GotRelative,
|
||||
encoding: RelocationEncoding::Generic,
|
||||
symbol: sym_id,
|
||||
addend: -4,
|
||||
}
|
||||
} else {
|
||||
internal_error!("failed to find data symbol for {:?}", name);
|
||||
}
|
||||
}
|
||||
Relocation::JmpToReturn { offset, .. } => unreachable!(),
|
||||
};
|
||||
|
||||
output.add_relocation(text_section, relocation).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_wrapper<'a, B: Backend<'a>>(
|
||||
|
@ -357,7 +384,7 @@ fn build_object<'a, B: Backend<'a>>(
|
|||
module_id.register_debug_idents(ident_ids);
|
||||
}
|
||||
|
||||
// println!("{}", test_helper.to_pretty(backend.interner(), 200, true));
|
||||
println!("{}", test_helper.to_pretty(backend.interner(), 200, true));
|
||||
|
||||
build_proc_symbol(
|
||||
&mut output,
|
||||
|
|
|
@ -945,11 +945,11 @@ fn test_helper_body<'a>(
|
|||
let result = |next| Stmt::Let(result_symbol, result_expr, main_proc.ret_layout, next);
|
||||
|
||||
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_expr = Expr::Literal(Literal::Int((0 as i128).to_ne_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_expr = Expr::Literal(Literal::Int((0 as i128).to_ne_bytes()));
|
||||
let msg_ptr = |next| Stmt::Let(msg_ptr_symbol, msg_ptr_expr, Layout::U64, next);
|
||||
|
||||
// construct the record
|
||||
|
@ -991,16 +991,17 @@ fn test_helper_body<'a>(
|
|||
},
|
||||
arguments: env.arena.alloc([alloca_symbol]),
|
||||
});
|
||||
let load = |next| Stmt::Let(load_symbol, load_expr, Layout::U64, next);
|
||||
let load = |next| Stmt::Let(load_symbol, load_expr, main_proc.ret_layout, next);
|
||||
|
||||
// is_longjmp_symbol will the pointer to the error message
|
||||
let err_tag_symbol = env.create_symbol(ident_ids, "err_tag");
|
||||
let err_tag_expr = Expr::Literal(Literal::Int((1 as i128).to_be_bytes()));
|
||||
let err_tag_expr = Expr::Literal(Literal::Int((1 as i128).to_ne_bytes()));
|
||||
let err_tag = |next| Stmt::Let(err_tag_symbol, err_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);
|
||||
// let msg_ptr_symbol = env.create_symbol(ident_ids, "msg_ptr");
|
||||
// let msg_ptr_expr = Expr::Literal(Literal::Int((0 as i128).to_ne_bytes()));
|
||||
// let msg_ptr = |next| Stmt::Let(msg_ptr_symbol, msg_ptr_expr, Layout::U64, next);
|
||||
let msg_ptr_symbol = is_longjmp_symbol;
|
||||
|
||||
// construct the record
|
||||
let output_symbol = env.create_symbol(ident_ids, "output_err");
|
||||
|
@ -1015,13 +1016,13 @@ fn test_helper_body<'a>(
|
|||
//
|
||||
err_tag(arena.alloc(
|
||||
//
|
||||
msg_ptr(arena.alloc(
|
||||
// msg_ptr(arena.alloc(
|
||||
//
|
||||
output(arena.alloc(
|
||||
//
|
||||
output(arena.alloc(
|
||||
//
|
||||
Stmt::Ret(output_symbol),
|
||||
)),
|
||||
Stmt::Ret(output_symbol),
|
||||
)),
|
||||
// )),
|
||||
)),
|
||||
)),
|
||||
)))
|
||||
|
|
|
@ -994,7 +994,7 @@ fn undefined_variable() {
|
|||
|
||||
#[test]
|
||||
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm", feature = "gen-dev"))]
|
||||
#[should_panic(expected = "Roc failed with message: ")]
|
||||
#[should_panic(expected = "Roc failed with message: a crash")]
|
||||
fn a_crash() {
|
||||
assert_evals_to!(
|
||||
indoc!(
|
||||
|
|
|
@ -360,11 +360,9 @@ macro_rules! assert_evals_to {
|
|||
);
|
||||
}
|
||||
|
||||
dbg!(&result);
|
||||
|
||||
match result.into_result() {
|
||||
Ok(value) => transform(value),
|
||||
Err((msg, _tag)) => panic!("roc_panic: {msg}"),
|
||||
Err((msg, _tag)) => panic!("Roc failed with message: {msg}"),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue