This commit is contained in:
Folkert 2023-07-26 22:53:15 +02:00
parent 644def72f1
commit f59eed6366
No known key found for this signature in database
GPG key ID: 1F17F6FFD112B97C
8 changed files with 107 additions and 33 deletions

View file

@ -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| {

View file

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

View file

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

View file

@ -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.

View file

@ -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,

View file

@ -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),
)),
// )),
)),
)),
)))

View file

@ -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!(

View file

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