mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 13:59:08 +00:00
indirec inc/dec generation in mono helpers
This commit is contained in:
parent
04081ae8b3
commit
6ed899d8be
6 changed files with 219 additions and 65 deletions
|
@ -697,6 +697,9 @@ impl<
|
|||
fn helper_proc_symbols(&self) -> &Vec<'a, (Symbol, ProcLayout<'a>)> {
|
||||
&self.helper_proc_symbols
|
||||
}
|
||||
fn caller_procs(&self) -> &Vec<'a, CallerProc<'a>> {
|
||||
&self.caller_procs
|
||||
}
|
||||
|
||||
fn reset(&mut self, name: String, is_self_recursive: SelfRecursive) {
|
||||
self.proc_name = Some(name);
|
||||
|
@ -1653,28 +1656,40 @@ impl<
|
|||
)
|
||||
}
|
||||
|
||||
fn gen_refcount_proc_dec(&mut self, layout: InLayout<'a>) -> Symbol {
|
||||
fn build_indirect_inc(&mut self, layout: InLayout<'a>) -> Symbol {
|
||||
let ident_ids = self
|
||||
.interns
|
||||
.all_ident_ids
|
||||
.get_mut(&self.env.module_id)
|
||||
.unwrap();
|
||||
|
||||
let (refcount_proc_name, _) = self.helper_proc_gen.gen_refcount_proc(
|
||||
let (refcount_proc_name, linker_data) = self.helper_proc_gen.gen_refcount_proc(
|
||||
ident_ids,
|
||||
self.layout_interner,
|
||||
layout,
|
||||
HelperOp::Dec,
|
||||
HelperOp::IndirectInc,
|
||||
);
|
||||
|
||||
let proc_layout = ProcLayout {
|
||||
arguments: self.env().arena.alloc([layout]),
|
||||
result: Layout::UNIT,
|
||||
niche: roc_mono::layout::Niche::NONE,
|
||||
};
|
||||
self.helper_proc_symbols_mut().extend(linker_data);
|
||||
|
||||
self.helper_proc_symbols_mut()
|
||||
.push((refcount_proc_name, proc_layout));
|
||||
refcount_proc_name
|
||||
}
|
||||
|
||||
fn build_indirect_dec(&mut self, layout: InLayout<'a>) -> Symbol {
|
||||
let ident_ids = self
|
||||
.interns
|
||||
.all_ident_ids
|
||||
.get_mut(&self.env.module_id)
|
||||
.unwrap();
|
||||
|
||||
let (refcount_proc_name, linker_data) = self.helper_proc_gen.gen_refcount_proc(
|
||||
ident_ids,
|
||||
self.layout_interner,
|
||||
layout,
|
||||
HelperOp::IndirectDec,
|
||||
);
|
||||
|
||||
self.helper_proc_symbols_mut().extend(linker_data);
|
||||
|
||||
refcount_proc_name
|
||||
}
|
||||
|
@ -1691,13 +1706,6 @@ impl<
|
|||
.get_mut(&self.env.module_id)
|
||||
.unwrap();
|
||||
|
||||
let (inc_n_data_symbol, inc_n_data_linker_data) = self.helper_proc_gen.gen_refcount_proc(
|
||||
ident_ids,
|
||||
self.layout_interner,
|
||||
Layout::UNIT,
|
||||
HelperOp::Inc,
|
||||
);
|
||||
|
||||
let caller_proc = CallerProc::new(
|
||||
self.env.arena,
|
||||
self.env.module_id,
|
||||
|
@ -1726,17 +1734,6 @@ impl<
|
|||
self.load_layout_stack_size(old_element_layout, old_element_width);
|
||||
self.load_layout_stack_size(new_element_layout, new_element_width);
|
||||
|
||||
self.helper_proc_symbols.extend(inc_n_data_linker_data);
|
||||
self.helper_proc_symbols
|
||||
.extend([(caller_proc.proc_symbol, caller_proc.proc_layout)]);
|
||||
|
||||
let inc_n_data_string = self.function_symbol_to_string(
|
||||
inc_n_data_symbol,
|
||||
std::iter::empty(),
|
||||
None,
|
||||
Layout::UNIT,
|
||||
);
|
||||
|
||||
let caller_string = self.function_symbol_to_string(
|
||||
caller_proc.proc_symbol,
|
||||
std::iter::empty(),
|
||||
|
@ -1744,10 +1741,17 @@ impl<
|
|||
Layout::UNIT,
|
||||
);
|
||||
|
||||
// self.helper_proc_symbols .extend([(caller_proc.proc_symbol, caller_proc.proc_layout)]);
|
||||
self.caller_procs.push(caller_proc);
|
||||
|
||||
let inc_n_data = Symbol::DEV_TMP;
|
||||
self.build_fn_pointer(&inc_n_data, inc_n_data_string);
|
||||
// function pointer to a function that takes a pointer, and increments
|
||||
let inc_n_data = if let Some(closure_env_layout) = higher_order.closure_env_layout {
|
||||
self.increment_fn_pointer(closure_env_layout)
|
||||
} else {
|
||||
// null pointer
|
||||
self.load_literal_i64(&Symbol::DEV_TMP, 0);
|
||||
Symbol::DEV_TMP
|
||||
};
|
||||
|
||||
self.build_fn_pointer(&caller, caller_string);
|
||||
|
||||
|
@ -1771,10 +1775,14 @@ impl<
|
|||
self.load_literal(&data, &Layout::U64, &Literal::Int(0u128.to_be_bytes()));
|
||||
}
|
||||
|
||||
// we pass a null pointer when the data is not owned. the zig code must not call this!
|
||||
let data_is_owned = higher_order.closure_env_layout.is_some()
|
||||
&& higher_order.passed_function.owns_captured_environment;
|
||||
|
||||
self.load_literal(
|
||||
&Symbol::DEV_TMP2,
|
||||
&Layout::BOOL,
|
||||
&Literal::Bool(higher_order.passed_function.owns_captured_environment),
|
||||
&Literal::Bool(data_is_owned),
|
||||
);
|
||||
|
||||
// list: RocList,
|
||||
|
|
|
@ -195,23 +195,36 @@ trait Backend<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn decrement_fn_pointer(
|
||||
&mut self,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
layout: InLayout<'a>,
|
||||
) -> Symbol {
|
||||
let arena = self.env().arena;
|
||||
fn increment_fn_pointer(&mut self, layout: InLayout<'a>) -> Symbol {
|
||||
let box_layout = self.interner_mut().insert(Layout::Boxed(layout));
|
||||
|
||||
let element_increment = self.debug_symbol("element_increment");
|
||||
let element_increment_symbol = self.build_indirect_inc(layout);
|
||||
|
||||
let element_increment_string = self.function_symbol_to_string(
|
||||
element_increment_symbol,
|
||||
[box_layout].into_iter(),
|
||||
None,
|
||||
Layout::UNIT,
|
||||
);
|
||||
|
||||
self.build_fn_pointer(&element_increment, element_increment_string);
|
||||
|
||||
element_increment
|
||||
}
|
||||
|
||||
fn decrement_fn_pointer(&mut self, layout: InLayout<'a>) -> Symbol {
|
||||
let box_layout = self.interner_mut().insert(Layout::Boxed(layout));
|
||||
|
||||
let element_decrement = self.debug_symbol("element_decrement");
|
||||
let element_decrement_symbol = self.gen_refcount_proc_dec(layout);
|
||||
let element_decrement_layout = ProcLayout {
|
||||
arguments: arena.alloc([layout]),
|
||||
result: Layout::UNIT,
|
||||
niche: roc_mono::layout::Niche::NONE,
|
||||
};
|
||||
let element_decrement_string = layout_ids
|
||||
.get_toplevel(element_decrement_symbol, &element_decrement_layout)
|
||||
.to_symbol_string(element_decrement_symbol, self.interns());
|
||||
let element_decrement_symbol = self.build_indirect_dec(layout);
|
||||
|
||||
let element_decrement_string = self.function_symbol_to_string(
|
||||
element_decrement_symbol,
|
||||
[box_layout].into_iter(),
|
||||
None,
|
||||
Layout::UNIT,
|
||||
);
|
||||
|
||||
self.build_fn_pointer(&element_decrement, element_decrement_string);
|
||||
|
||||
|
@ -223,6 +236,7 @@ trait Backend<'a> {
|
|||
fn helper_proc_symbols_mut(&mut self) -> &mut Vec<'a, (Symbol, ProcLayout<'a>)>;
|
||||
|
||||
fn helper_proc_symbols(&self) -> &Vec<'a, (Symbol, ProcLayout<'a>)>;
|
||||
fn caller_procs(&self) -> &Vec<'a, CallerProc<'a>>;
|
||||
|
||||
/// reset resets any registers or other values that may be occupied at the end of a procedure.
|
||||
/// It also passes basic procedure information to the builder for setup of the next function.
|
||||
|
@ -263,6 +277,7 @@ trait Backend<'a> {
|
|||
self.scan_ast(&proc.body);
|
||||
self.create_free_map();
|
||||
self.build_stmt(layout_ids, &proc.body, &proc.ret_layout);
|
||||
|
||||
let mut helper_proc_names = bumpalo::vec![in self.env().arena];
|
||||
helper_proc_names.reserve(self.helper_proc_symbols().len());
|
||||
for (rc_proc_sym, rc_proc_layout) in self.helper_proc_symbols() {
|
||||
|
@ -272,6 +287,17 @@ trait Backend<'a> {
|
|||
|
||||
helper_proc_names.push((*rc_proc_sym, name));
|
||||
}
|
||||
|
||||
for caller_proc in self.caller_procs() {
|
||||
let proc_layout = caller_proc.proc_layout;
|
||||
let proc_symbol = caller_proc.proc_symbol;
|
||||
let name = layout_ids
|
||||
.get_toplevel(proc_symbol, &proc_layout)
|
||||
.to_symbol_string(proc_symbol, self.interns());
|
||||
|
||||
helper_proc_names.push((proc_symbol, name));
|
||||
}
|
||||
|
||||
let (bytes, relocs) = self.finalize();
|
||||
(bytes, relocs, helper_proc_names)
|
||||
}
|
||||
|
@ -285,7 +311,7 @@ trait Backend<'a> {
|
|||
) {
|
||||
match stmt {
|
||||
Stmt::Let(sym, expr, layout, following) => {
|
||||
self.build_expr(layout_ids, sym, expr, layout);
|
||||
self.build_expr(sym, expr, layout);
|
||||
self.set_layout_map(*sym, layout);
|
||||
self.free_symbols(stmt);
|
||||
self.build_stmt(layout_ids, following, ret_layout);
|
||||
|
@ -430,13 +456,7 @@ trait Backend<'a> {
|
|||
|
||||
/// build_expr builds the expressions for the specified symbol.
|
||||
/// The builder must keep track of the symbol because it may be referred to later.
|
||||
fn build_expr(
|
||||
&mut self,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
sym: &Symbol,
|
||||
expr: &Expr<'a>,
|
||||
layout: &InLayout<'a>,
|
||||
) {
|
||||
fn build_expr(&mut self, sym: &Symbol, expr: &Expr<'a>, layout: &InLayout<'a>) {
|
||||
match expr {
|
||||
Expr::Literal(lit) => {
|
||||
if self.env().lazy_literals {
|
||||
|
@ -460,7 +480,6 @@ trait Backend<'a> {
|
|||
LowLevelWrapperType::from_symbol(func_sym.name())
|
||||
{
|
||||
return self.build_run_low_level(
|
||||
layout_ids,
|
||||
sym,
|
||||
&lowlevel,
|
||||
arguments,
|
||||
|
@ -505,7 +524,6 @@ trait Backend<'a> {
|
|||
}
|
||||
|
||||
self.build_run_low_level(
|
||||
layout_ids,
|
||||
sym,
|
||||
lowlevel,
|
||||
arguments,
|
||||
|
@ -613,7 +631,6 @@ trait Backend<'a> {
|
|||
/// The builder must keep track of the symbol because it may be referred to later.
|
||||
fn build_run_low_level(
|
||||
&mut self,
|
||||
layout_ids: &mut LayoutIds<'a>,
|
||||
sym: &Symbol,
|
||||
lowlevel: &LowLevel,
|
||||
args: &'a [Symbol],
|
||||
|
@ -1337,7 +1354,7 @@ trait Backend<'a> {
|
|||
list_argument.element_width,
|
||||
start,
|
||||
len,
|
||||
self.decrement_fn_pointer(layout_ids, element_layout),
|
||||
self.decrement_fn_pointer(element_layout),
|
||||
];
|
||||
|
||||
let layout_usize = Layout::U64;
|
||||
|
@ -1438,7 +1455,7 @@ trait Backend<'a> {
|
|||
self.load_literal_i8(&update_mode, UpdateMode::Immutable as i8);
|
||||
|
||||
let layout_usize = Layout::U64;
|
||||
let element_decrement = self.decrement_fn_pointer(layout_ids, element_layout);
|
||||
let element_decrement = self.decrement_fn_pointer(element_layout);
|
||||
|
||||
// list: RocList,
|
||||
// alignment: u32,
|
||||
|
@ -1759,7 +1776,8 @@ trait Backend<'a> {
|
|||
ret_layout: InLayout<'a>,
|
||||
);
|
||||
|
||||
fn gen_refcount_proc_dec(&mut self, layout: InLayout<'a>) -> Symbol;
|
||||
fn build_indirect_inc(&mut self, layout: InLayout<'a>) -> Symbol;
|
||||
fn build_indirect_dec(&mut self, layout: InLayout<'a>) -> Symbol;
|
||||
|
||||
/// build_list_with_capacity creates and returns a list with the given capacity.
|
||||
fn build_list_with_capacity(
|
||||
|
|
|
@ -305,6 +305,10 @@ fn build_object<'a, B: Backend<'a>>(
|
|||
}
|
||||
|
||||
// Generate IR for specialized helper procs (refcounting & equality)
|
||||
let empty = bumpalo::collections::Vec::new_in(arena);
|
||||
let mut helper_symbols_and_layouts =
|
||||
std::mem::replace(backend.helper_proc_symbols_mut(), empty);
|
||||
|
||||
let helper_procs = {
|
||||
let (module_id, _interner, interns, helper_proc_gen, caller_procs) =
|
||||
backend.module_interns_helpers_mut();
|
||||
|
@ -315,18 +319,24 @@ fn build_object<'a, B: Backend<'a>>(
|
|||
let ident_ids = interns.all_ident_ids.get_mut(&module_id).unwrap();
|
||||
let mut helper_procs = helper_proc_gen.take_procs();
|
||||
|
||||
helper_procs.extend(owned_caller_procs.into_iter().map(|cp| cp.proc));
|
||||
for caller_proc in owned_caller_procs {
|
||||
helper_symbols_and_layouts.push((caller_proc.proc_symbol, caller_proc.proc_layout));
|
||||
helper_procs.push(caller_proc.proc);
|
||||
}
|
||||
|
||||
module_id.register_debug_idents(ident_ids);
|
||||
|
||||
helper_procs
|
||||
};
|
||||
|
||||
let empty = bumpalo::collections::Vec::new_in(arena);
|
||||
let helper_symbols_and_layouts = std::mem::replace(backend.helper_proc_symbols_mut(), empty);
|
||||
let mut helper_names_symbols_procs = Vec::with_capacity_in(helper_procs.len(), arena);
|
||||
|
||||
debug_assert_eq!(helper_symbols_and_layouts.len(), helper_procs.len());
|
||||
|
||||
// Names and linker data for helpers
|
||||
for ((sym, layout), proc) in helper_symbols_and_layouts.into_iter().zip(helper_procs) {
|
||||
debug_assert_eq!(sym, proc.name.name());
|
||||
|
||||
let fn_name = backend.function_symbol_to_string(
|
||||
sym,
|
||||
layout.arguments.iter().copied(),
|
||||
|
@ -641,6 +651,7 @@ fn build_proc<'a, B: Backend<'a>>(
|
|||
};
|
||||
output.add_symbol(builtin_symbol);
|
||||
}
|
||||
|
||||
// If the symbol is an undefined reference counting procedure, we need to add it here.
|
||||
if output.symbol_id(name.as_bytes()).is_none() {
|
||||
for (sym, rc_name) in rc_proc_names.iter() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue