Generate roc_alloc etc in dev_num tests

This commit is contained in:
Richard Feldman 2021-05-24 21:36:27 -04:00
parent 0b3715ebee
commit 595c704e88
4 changed files with 90 additions and 0 deletions

View file

@ -341,6 +341,16 @@ impl<
Ok(())
}
/// Used for generating wrappers for malloc/realloc/free
fn build_wrapped_jmp(&mut self) -> Result<(&'a [u8], u64), String> {
let mut out = bumpalo::vec![in self.env.arena];
ASM::jmp_imm32(&mut out, 0);
let offset = out.len() as u64 - 4;
Ok((out.into_bump_slice(), offset))
}
fn build_fn_call(
&mut self,
dst: &Symbol,

View file

@ -22,6 +22,7 @@ pub struct Env<'a> {
pub interns: Interns,
pub exposed_to_host: MutSet<Symbol>,
pub lazy_literals: bool,
pub generate_allocators: bool,
}
// These relocations likely will need a length.
@ -67,6 +68,9 @@ where
// The backend should track these args so it can use them as needed.
fn load_args(&mut self, args: &'a [(Layout<'a>, Symbol)]) -> Result<(), String>;
/// Used for generating wrappers for malloc/realloc/free
fn build_wrapped_jmp(&mut self) -> Result<(&'a [u8], u64), String>;
/// build_proc creates a procedure and outputs it to the wrapped object writer.
fn build_proc(&mut self, proc: Proc<'a>) -> Result<(&'a [u8], &[Relocation]), String> {
self.reset();

View file

@ -89,6 +89,60 @@ pub fn build_module<'a>(
}
}
fn generate_wrapper<'a, B: Backend<'a>>(
backend: &mut B,
output: &mut Object,
wrapper_name: String,
wraps: String,
) -> Result<(), String> {
let text_section = output.section_id(StandardSection::Text);
let proc_symbol = Symbol {
name: wrapper_name.as_bytes().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, offset) = backend.build_wrapped_jmp()?;
let proc_offset = output.add_symbol_data(proc_id, text_section, proc_data, 16);
let name = wraps.as_str().as_bytes();
// If the symbol is an undefined zig builtin, we need to add it here.
let symbol = Symbol {
name: name.to_vec(),
value: 0,
size: 0,
kind: SymbolKind::Text,
scope: SymbolScope::Linkage,
weak: false,
section: SymbolSection::Undefined,
flags: SymbolFlags::None,
};
output.add_symbol(symbol);
if let Some(sym_id) = output.symbol_id(name) {
let reloc = write::Relocation {
offset: offset + proc_offset,
size: 32,
kind: RelocationKind::PltRelative,
encoding: RelocationEncoding::X86Branch,
symbol: sym_id,
addend: -4,
};
output
.add_relocation(text_section, reloc)
.map_err(|e| format!("{:?}", e))?;
Ok(())
} else {
Err(format!("failed to find fn symbol for {:?}", wraps))
}
}
fn build_object<'a, B: Backend<'a>>(
env: &'a Env,
procedures: MutMap<(symbol::Symbol, Layout<'a>), Proc<'a>>,
@ -107,6 +161,27 @@ fn build_object<'a, B: Backend<'a>>(
);
*/
if env.generate_allocators {
generate_wrapper(
&mut backend,
&mut output,
"roc_alloc".into(),
"malloc".into(),
)?;
generate_wrapper(
&mut backend,
&mut output,
"roc_realloc".into(),
"realloc".into(),
)?;
generate_wrapper(
&mut backend,
&mut output,
"roc_dealloc".into(),
"free".into(),
)?;
}
// Setup layout_ids for procedure calls.
let mut layout_ids = roc_mono::layout::LayoutIds::default();
let mut procs = Vec::with_capacity_in(procedures.len(), env.arena);