mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
glue getters in mono
This commit is contained in:
parent
c4016547af
commit
c9aedff3e8
4 changed files with 205 additions and 4 deletions
|
@ -297,6 +297,7 @@ fn gen_from_mono_module_llvm(
|
||||||
&env,
|
&env,
|
||||||
opt_level,
|
opt_level,
|
||||||
loaded.procedures,
|
loaded.procedures,
|
||||||
|
&loaded.glue_layouts,
|
||||||
opt_entry_point,
|
opt_entry_point,
|
||||||
Some(&app_ll_file),
|
Some(&app_ll_file),
|
||||||
);
|
);
|
||||||
|
|
|
@ -4371,6 +4371,7 @@ pub fn build_procedures<'a, 'ctx, 'env>(
|
||||||
env: &Env<'a, 'ctx, 'env>,
|
env: &Env<'a, 'ctx, 'env>,
|
||||||
opt_level: OptLevel,
|
opt_level: OptLevel,
|
||||||
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
|
procedures: MutMap<(Symbol, ProcLayout<'a>), roc_mono::ir::Proc<'a>>,
|
||||||
|
_glue_layouts: &[Layout<'a>],
|
||||||
opt_entry_point: Option<EntryPoint<'a>>,
|
opt_entry_point: Option<EntryPoint<'a>>,
|
||||||
debug_output_file: Option<&Path>,
|
debug_output_file: Option<&Path>,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -703,6 +703,7 @@ pub struct MonomorphizedModule<'a> {
|
||||||
pub sources: MutMap<ModuleId, (PathBuf, Box<str>)>,
|
pub sources: MutMap<ModuleId, (PathBuf, Box<str>)>,
|
||||||
pub timings: MutMap<ModuleId, ModuleTiming>,
|
pub timings: MutMap<ModuleId, ModuleTiming>,
|
||||||
pub expectations: VecMap<ModuleId, Expectations>,
|
pub expectations: VecMap<ModuleId, Expectations>,
|
||||||
|
pub glue_layouts: Vec<Layout<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -1642,8 +1643,13 @@ fn state_thread_step<'a>(
|
||||||
// We're done! There should be no more messages pending.
|
// We're done! There should be no more messages pending.
|
||||||
debug_assert!(msg_rx.is_empty());
|
debug_assert!(msg_rx.is_empty());
|
||||||
|
|
||||||
let monomorphized =
|
let monomorphized = finish_specialization(
|
||||||
finish_specialization(state, subs, layout_interner, exposed_to_host)?;
|
arena,
|
||||||
|
state,
|
||||||
|
subs,
|
||||||
|
layout_interner,
|
||||||
|
exposed_to_host,
|
||||||
|
)?;
|
||||||
|
|
||||||
Ok(ControlFlow::Break(LoadResult::Monomorphized(monomorphized)))
|
Ok(ControlFlow::Break(LoadResult::Monomorphized(monomorphized)))
|
||||||
}
|
}
|
||||||
|
@ -2891,9 +2897,10 @@ fn log_layout_stats(module_id: ModuleId, layout_cache: &LayoutCache) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish_specialization<'a>(
|
fn finish_specialization<'a>(
|
||||||
|
arena: &'a Bump,
|
||||||
state: State<'a>,
|
state: State<'a>,
|
||||||
subs: Subs,
|
subs: Subs,
|
||||||
layout_interner: STLayoutInterner<'a>,
|
mut layout_interner: STLayoutInterner<'a>,
|
||||||
exposed_to_host: ExposedToHost,
|
exposed_to_host: ExposedToHost,
|
||||||
) -> Result<MonomorphizedModule<'a>, LoadingProblem<'a>> {
|
) -> Result<MonomorphizedModule<'a>, LoadingProblem<'a>> {
|
||||||
if false {
|
if false {
|
||||||
|
@ -2925,12 +2932,13 @@ fn finish_specialization<'a>(
|
||||||
|
|
||||||
let State {
|
let State {
|
||||||
toplevel_expects,
|
toplevel_expects,
|
||||||
procedures,
|
mut procedures,
|
||||||
module_cache,
|
module_cache,
|
||||||
output_path,
|
output_path,
|
||||||
platform_path,
|
platform_path,
|
||||||
platform_data,
|
platform_data,
|
||||||
exec_mode,
|
exec_mode,
|
||||||
|
ident_ids_by_module,
|
||||||
..
|
..
|
||||||
} = state;
|
} = state;
|
||||||
|
|
||||||
|
@ -3004,6 +3012,30 @@ fn finish_specialization<'a>(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let mut glue_layouts = Vec::new();
|
||||||
|
|
||||||
|
if let EntryPoint::Executable { symbol, layout, .. } = &entry_point {
|
||||||
|
let mut locked = ident_ids_by_module.lock();
|
||||||
|
|
||||||
|
let ident_ids = locked.get_mut(&symbol.module_id()).unwrap();
|
||||||
|
|
||||||
|
let result = &layout.result;
|
||||||
|
let it = layout.arguments.iter().chain([result]);
|
||||||
|
|
||||||
|
for layout in it {
|
||||||
|
let glue_procs = roc_mono::ir::generate_glue_procs(
|
||||||
|
symbol.module_id(),
|
||||||
|
ident_ids,
|
||||||
|
arena,
|
||||||
|
&mut layout_interner,
|
||||||
|
*layout,
|
||||||
|
);
|
||||||
|
|
||||||
|
procedures.extend(glue_procs.procs);
|
||||||
|
glue_layouts.extend(glue_procs.layouts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let output_path = match output_path {
|
let output_path = match output_path {
|
||||||
Some(path_str) => Path::new(path_str).into(),
|
Some(path_str) => Path::new(path_str).into(),
|
||||||
None => current_dir().unwrap().join(DEFAULT_APP_OUTPUT_PATH).into(),
|
None => current_dir().unwrap().join(DEFAULT_APP_OUTPUT_PATH).into(),
|
||||||
|
@ -3024,6 +3056,7 @@ fn finish_specialization<'a>(
|
||||||
sources,
|
sources,
|
||||||
timings: state.timings,
|
timings: state.timings,
|
||||||
toplevel_expects,
|
toplevel_expects,
|
||||||
|
glue_layouts,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10761,3 +10761,169 @@ where
|
||||||
remainder: env.arena.alloc(switch),
|
remainder: env.arena.alloc(switch),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn layout_contains_function(arena: &Bump, layout: Layout) -> bool {
|
||||||
|
let mut stack = Vec::new_in(arena);
|
||||||
|
|
||||||
|
stack.push(layout);
|
||||||
|
|
||||||
|
while let Some(layout) = stack.pop() {
|
||||||
|
match layout {
|
||||||
|
Layout::Builtin(builtin) => match builtin {
|
||||||
|
Builtin::Int(_)
|
||||||
|
| Builtin::Float(_)
|
||||||
|
| Builtin::Bool
|
||||||
|
| Builtin::Decimal
|
||||||
|
| Builtin::Str => { /* do nothing */ }
|
||||||
|
Builtin::List(element) => stack.push(*element),
|
||||||
|
},
|
||||||
|
Layout::Struct { field_layouts, .. } => stack.extend(field_layouts),
|
||||||
|
Layout::Boxed(boxed) => stack.push(*boxed),
|
||||||
|
Layout::Union(tag_union) => match tag_union {
|
||||||
|
UnionLayout::NonRecursive(tags) | UnionLayout::Recursive(tags) => {
|
||||||
|
for tag in tags {
|
||||||
|
stack.extend(tag.iter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnionLayout::NonNullableUnwrapped(fields) => {
|
||||||
|
stack.extend(fields);
|
||||||
|
}
|
||||||
|
UnionLayout::NullableWrapped { other_tags, .. } => {
|
||||||
|
for tag in other_tags {
|
||||||
|
stack.extend(tag.iter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnionLayout::NullableUnwrapped { other_fields, .. } => {
|
||||||
|
stack.extend(other_fields);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Layout::LambdaSet(_) => return true,
|
||||||
|
Layout::RecursivePointer => {
|
||||||
|
/* do nothing, we've already generated for this type through the Union(_) */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GlueProcs<'a> {
|
||||||
|
pub procs: Vec<'a, ((Symbol, ProcLayout<'a>), Proc<'a>)>,
|
||||||
|
pub layouts: Vec<'a, Layout<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_glue_procs<'a>(
|
||||||
|
home: ModuleId,
|
||||||
|
ident_ids: &mut IdentIds,
|
||||||
|
arena: &'a Bump,
|
||||||
|
layout_interner: &mut STLayoutInterner<'a>,
|
||||||
|
layout: Layout<'a>,
|
||||||
|
) -> GlueProcs<'a> {
|
||||||
|
let mut stack = Vec::new_in(arena);
|
||||||
|
let mut procs = Vec::new_in(arena);
|
||||||
|
let mut layouts = Vec::new_in(arena);
|
||||||
|
|
||||||
|
stack.push(layout);
|
||||||
|
|
||||||
|
while let Some(layout) = stack.pop() {
|
||||||
|
match layout {
|
||||||
|
Layout::Builtin(builtin) => match builtin {
|
||||||
|
Builtin::Int(_)
|
||||||
|
| Builtin::Float(_)
|
||||||
|
| Builtin::Bool
|
||||||
|
| Builtin::Decimal
|
||||||
|
| Builtin::Str => { /* do nothing */ }
|
||||||
|
Builtin::List(element) => stack.push(*element),
|
||||||
|
},
|
||||||
|
Layout::Struct { field_layouts, .. } => {
|
||||||
|
if layout_contains_function(arena, layout) {
|
||||||
|
layouts.push(layout);
|
||||||
|
|
||||||
|
generate_glue_procs_for_fields(
|
||||||
|
home,
|
||||||
|
ident_ids,
|
||||||
|
arena,
|
||||||
|
layout,
|
||||||
|
field_layouts,
|
||||||
|
&mut procs,
|
||||||
|
);
|
||||||
|
|
||||||
|
stack.extend(field_layouts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Layout::Boxed(boxed) => stack.push(*boxed),
|
||||||
|
Layout::Union(tag_union) => match tag_union {
|
||||||
|
UnionLayout::NonRecursive(tags) | UnionLayout::Recursive(tags) => {
|
||||||
|
for tag in tags {
|
||||||
|
stack.extend(tag.iter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnionLayout::NonNullableUnwrapped(fields) => {
|
||||||
|
stack.extend(fields);
|
||||||
|
}
|
||||||
|
UnionLayout::NullableWrapped { other_tags, .. } => {
|
||||||
|
for tag in other_tags {
|
||||||
|
stack.extend(tag.iter());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnionLayout::NullableUnwrapped { other_fields, .. } => {
|
||||||
|
stack.extend(other_fields);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Layout::LambdaSet(lambda_set) => {
|
||||||
|
stack.push(lambda_set.runtime_representation(layout_interner))
|
||||||
|
}
|
||||||
|
Layout::RecursivePointer => {
|
||||||
|
/* do nothing, we've already generated for this type through the Union(_) */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GlueProcs { procs, layouts }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_glue_procs_for_fields<'a>(
|
||||||
|
home: ModuleId,
|
||||||
|
ident_ids: &mut IdentIds,
|
||||||
|
arena: &'a Bump,
|
||||||
|
struct_layout: Layout<'a>,
|
||||||
|
field_layouts: &'a [Layout<'a>],
|
||||||
|
output: &mut Vec<'a, ((Symbol, ProcLayout<'a>), Proc<'a>)>,
|
||||||
|
) {
|
||||||
|
output.reserve(field_layouts.len());
|
||||||
|
|
||||||
|
for (index, field) in field_layouts.iter().enumerate() {
|
||||||
|
let symbol = Symbol::new(home, ident_ids.gen_unique());
|
||||||
|
let argument = Symbol::new(home, ident_ids.gen_unique());
|
||||||
|
let result = Symbol::new(home, ident_ids.gen_unique());
|
||||||
|
|
||||||
|
let proc_layout = ProcLayout {
|
||||||
|
arguments: arena.alloc([struct_layout]),
|
||||||
|
result: *field,
|
||||||
|
captures_niche: CapturesNiche::no_niche(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let expr = Expr::StructAtIndex {
|
||||||
|
index: index as u64,
|
||||||
|
field_layouts,
|
||||||
|
structure: argument,
|
||||||
|
};
|
||||||
|
|
||||||
|
let ret_stmt = arena.alloc(Stmt::Ret(result));
|
||||||
|
|
||||||
|
let body = Stmt::Let(result, expr, *field, ret_stmt);
|
||||||
|
|
||||||
|
let proc = Proc {
|
||||||
|
name: LambdaName::no_niche(symbol),
|
||||||
|
args: arena.alloc([(struct_layout, argument)]),
|
||||||
|
body,
|
||||||
|
closure_data_layout: None,
|
||||||
|
ret_layout: *field,
|
||||||
|
is_self_recursive: SelfRecursive::NotSelfRecursive,
|
||||||
|
must_own_arguments: false,
|
||||||
|
host_exposed_layouts: HostExposedLayouts::NotHostExposed,
|
||||||
|
};
|
||||||
|
|
||||||
|
output.push(((symbol, proc_layout), proc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue