WIP infer join points too

This commit is contained in:
Folkert 2024-06-28 15:44:04 +02:00
parent 0932c542ca
commit 047779d981
No known key found for this signature in database
GPG Key ID: 1F17F6FFD112B97C
18 changed files with 156 additions and 94 deletions

View File

@ -349,8 +349,9 @@ where
}
match opt_level {
OptLevel::Development | OptLevel::Normal => morphic_lib::solve_trivial(program),
OptLevel::Optimize | OptLevel::Size => morphic_lib::solve(program),
// OptLevel::Development | OptLevel::Normal => morphic_lib::solve_trivial(program),
// OptLevel::Optimize | OptLevel::Size => morphic_lib::solve(program),
_ => morphic_lib::solve_trivial(program),
}
}

View File

@ -1,11 +1,13 @@
use bumpalo::{collections::Vec, Bump};
use bumpalo::{
collections::{CollectIn, Vec},
Bump,
};
use roc_collections::{MutMap, ReferenceMatrix};
use roc_error_macros::todo_lambda_erasure;
use roc_module::symbol::Symbol;
use crate::{
inc_dec::Ownership,
ir::{Call, CallType, Expr, Proc, ProcLayout, Stmt},
ir::{Call, CallType, Expr, JoinPointId, Param, Proc, ProcLayout, Stmt},
layout::{Builtin, InLayout, LayoutInterner, LayoutRepr, Niche},
};
@ -46,15 +48,19 @@ impl BorrowSignature {
}
}
fn set(&mut self, index: usize, ownership: Ownership) {
fn set(&mut self, index: usize, ownership: Ownership) -> bool {
assert!(index < self.len());
let modified = self.get(index) != Some(&ownership);
let mask = 1 << (index + 8);
match ownership {
Ownership::Owned => self.0 |= mask,
Ownership::Borrowed => self.0 &= !mask,
}
modified
}
pub fn iter(&self) -> impl Iterator<Item = Ownership> + '_ {
@ -76,27 +82,35 @@ impl std::ops::Index<usize> for BorrowSignature {
}
}
pub(crate) type BorrowSignatures<'a> = MutMap<(Symbol, ProcLayout<'a>), BorrowSignature>;
pub(crate) struct BorrowSignatures<'a> {
pub(crate) procs: MutMap<(Symbol, ProcLayout<'a>), BorrowSignature>,
}
pub(crate) fn infer_borrow_signatures<'a, 'b: 'a>(
arena: &'a Bump,
interner: &impl LayoutInterner<'a>,
procs: &'b MutMap<(Symbol, ProcLayout<'a>), Proc<'a>>,
) -> BorrowSignatures<'a> {
let mut borrow_signatures: BorrowSignatures = procs
.iter()
.map(|(_key, proc)| {
let mut signature = BorrowSignature::new(proc.args.len());
let mut borrow_signatures: BorrowSignatures = BorrowSignatures {
procs: procs
.iter()
.map(|(_key, proc)| {
let mut signature = BorrowSignature::new(proc.args.len());
let key = (proc.name.name(), proc.proc_layout(arena));
let key = (proc.name.name(), proc.proc_layout(arena));
for (i, in_layout) in key.1.arguments.iter().enumerate() {
signature.set(i, layout_to_ownership(*in_layout, interner));
}
for (i, in_layout) in key.1.arguments.iter().enumerate() {
signature.set(i, layout_to_ownership(*in_layout, interner));
}
(key, signature)
})
.collect();
(key, signature)
})
.collect(),
};
let mut join_points: Vec<_> = std::iter::repeat_with(MutMap::default)
.take(procs.len())
.collect_in(arena);
// next we first partition the functions into strongly connected components, then do a
// topological sort on these components, finally run the fix-point borrow analysis on each
@ -105,6 +119,9 @@ pub(crate) fn infer_borrow_signatures<'a, 'b: 'a>(
let matrix = construct_reference_matrix(arena, procs);
let sccs = matrix.strongly_connected_components_all();
let mut join_point_stack = Vec::new_in(arena);
let mut proc_join_points = MutMap::default();
for (group, _) in sccs.groups() {
// This is a fixed-point analysis
//
@ -121,22 +138,38 @@ pub(crate) fn infer_borrow_signatures<'a, 'b: 'a>(
let (_, proc) = procs.iter().nth(index).unwrap();
let key = (proc.name.name(), proc.proc_layout(arena));
std::mem::swap(&mut proc_join_points, &mut join_points[index]);
if proc.args.is_empty() {
continue;
}
let mut state = State {
args: proc.args,
borrow_signature: *borrow_signatures.get(&key).unwrap(),
borrow_signature: *borrow_signatures.procs.get(&key).unwrap(),
join_point_stack,
join_points: proc_join_points,
modified: false,
};
state.inspect_stmt(&mut borrow_signatures, &proc.body);
state.inspect_stmt(interner, &mut borrow_signatures, &proc.body);
let Some(old) = borrow_signatures.insert(key, state.borrow_signature) else {
let Some(old) = borrow_signatures.procs.insert(key, state.borrow_signature) else {
unreachable!("key should be present");
};
modified |= old != state.borrow_signature
// TODO I think this should use state.modified, but that loops infinitely currently
// also maybe a change in join point signature is always immediately reflected in a
// change in proc signature, in which case using the join point changes may not
// have any effect.
modified |= old != state.borrow_signature;
proc_join_points = state.join_points;
std::mem::swap(&mut proc_join_points, &mut join_points[index]);
join_point_stack = state.join_point_stack;
join_point_stack.clear();
}
if !modified {
@ -156,7 +189,7 @@ fn infer_borrow_signature<'a>(
proc: &'a Proc<'a>,
) -> BorrowSignature {
let mut state = State::new(arena, interner, borrow_signatures, proc);
state.inspect_stmt(borrow_signatures, &proc.body);
state.inspect_stmt(interner, borrow_signatures, &proc.body);
state.borrow_signature
}
@ -165,6 +198,9 @@ struct State<'a> {
/// for which borrow inference might decide to pass as borrowed
args: &'a [(InLayout<'a>, Symbol)],
borrow_signature: BorrowSignature,
join_point_stack: Vec<'a, (JoinPointId, &'a [Param<'a>])>,
join_points: MutMap<JoinPointId, BorrowSignature>,
modified: bool,
}
fn layout_to_ownership<'a>(
@ -172,7 +208,8 @@ fn layout_to_ownership<'a>(
interner: &impl LayoutInterner<'a>,
) -> Ownership {
match interner.get_repr(in_layout) {
LayoutRepr::Builtin(Builtin::Str | Builtin::List(_)) => Ownership::Borrowed,
LayoutRepr::Builtin(Builtin::Str) => Ownership::Borrowed,
LayoutRepr::Builtin(Builtin::List(_)) => Ownership::Borrowed,
LayoutRepr::LambdaSet(inner) => {
layout_to_ownership(inner.runtime_representation(), interner)
}
@ -190,7 +227,7 @@ impl<'a> State<'a> {
let key = (proc.name.name(), proc.proc_layout(arena));
// initialize the borrow signature based on the layout if first time
let borrow_signature = borrow_signatures.entry(key).or_insert_with(|| {
let borrow_signature = borrow_signatures.procs.entry(key).or_insert_with(|| {
let mut borrow_signature = BorrowSignature::new(proc.args.len());
for (i, in_layout) in key.1.arguments.iter().enumerate() {
@ -203,6 +240,9 @@ impl<'a> State<'a> {
Self {
args: proc.args,
borrow_signature: *borrow_signature,
join_point_stack: Vec::new_in(arena),
join_points: MutMap::default(),
modified: false,
}
}
@ -211,15 +251,30 @@ impl<'a> State<'a> {
/// Currently argument symbols participate if `layout_to_ownership` returns `Borrowed` for their layout.
fn mark_owned(&mut self, symbol: Symbol) {
if let Some(index) = self.args.iter().position(|(_, s)| *s == symbol) {
self.borrow_signature.set(index, Ownership::Owned);
self.modified |= self.borrow_signature.set(index, Ownership::Owned);
}
for (id, params) in &self.join_point_stack {
if let Some(index) = params.iter().position(|p| p.symbol == symbol) {
self.modified |= self
.join_points
.get_mut(id)
.unwrap()
.set(index, Ownership::Owned);
}
}
}
fn inspect_stmt(&mut self, borrow_signatures: &mut BorrowSignatures<'a>, stmt: &'a Stmt<'a>) {
fn inspect_stmt(
&mut self,
interner: &impl LayoutInterner<'a>,
borrow_signatures: &mut BorrowSignatures<'a>,
stmt: &'a Stmt<'a>,
) {
match stmt {
Stmt::Let(_, expr, _, stmt) => {
self.inspect_expr(borrow_signatures, expr);
self.inspect_stmt(borrow_signatures, stmt);
self.inspect_stmt(interner, borrow_signatures, stmt);
}
Stmt::Switch {
branches,
@ -227,9 +282,9 @@ impl<'a> State<'a> {
..
} => {
for (_, _, stmt) in branches.iter() {
self.inspect_stmt(borrow_signatures, stmt);
self.inspect_stmt(interner, borrow_signatures, stmt);
}
self.inspect_stmt(borrow_signatures, default_branch.1);
self.inspect_stmt(interner, borrow_signatures, default_branch.1);
}
Stmt::Ret(s) => {
// to return a value we must own it
@ -239,20 +294,47 @@ impl<'a> State<'a> {
Stmt::Refcounting(_, _) => unreachable!("not inserted yet"),
Stmt::Expect { remainder, .. } | Stmt::ExpectFx { remainder, .. } => {
// based on my reading of inc_dec.rs, expect borrows the symbols
self.inspect_stmt(borrow_signatures, remainder);
self.inspect_stmt(interner, borrow_signatures, remainder);
}
Stmt::Dbg { remainder, .. } => {
// based on my reading of inc_dec.rs, expect borrows the symbol
self.inspect_stmt(borrow_signatures, remainder);
self.inspect_stmt(interner, borrow_signatures, remainder);
}
Stmt::Join {
body, remainder, ..
id,
parameters,
body,
remainder,
} => {
self.inspect_stmt(borrow_signatures, body);
self.inspect_stmt(borrow_signatures, remainder);
self.join_points.entry(*id).or_insert_with(|| {
let mut signature = BorrowSignature::new(parameters.len());
for (i, param) in parameters.iter().enumerate() {
signature.set(i, layout_to_ownership(param.layout, interner));
}
signature
});
self.join_point_stack.push((*id, parameters));
self.inspect_stmt(interner, borrow_signatures, body);
self.join_point_stack.pop().unwrap();
self.inspect_stmt(interner, borrow_signatures, remainder);
}
Stmt::Jump(_, _) | Stmt::Crash(_, _) => { /* not relevant for ownership */ }
Stmt::Jump(id, arguments) => {
let borrow_signature = match self.join_points.get(id) {
Some(s) => *s,
None => unreachable!("no borrow signature for join point {id:?} layout"),
};
for (argument, ownership) in arguments.iter().zip(borrow_signature.iter()) {
if let Ownership::Owned = ownership {
self.mark_owned(*argument);
}
}
}
Stmt::Crash(_, _) => { /* not relevant for ownership */ }
}
}
@ -281,10 +363,11 @@ impl<'a> State<'a> {
niche: Niche::NONE,
};
let borrow_signature = match borrow_signatures.get(&(name.name(), proc_layout)) {
Some(s) => s,
None => unreachable!("no borrow signature for {name:?} layout"),
};
let borrow_signature =
match borrow_signatures.procs.get(&(name.name(), proc_layout)) {
Some(s) => s,
None => unreachable!("no borrow signature for {name:?} layout"),
};
for (argument, ownership) in arguments.iter().zip(borrow_signature.iter()) {
if let Ownership::Owned = ownership {

View File

@ -38,7 +38,7 @@ pub fn insert_inc_dec_operations<'a>(
let borrow_signatures = crate::borrow::infer_borrow_signatures(arena, layout_interner, ps);
let borrow_signatures = arena.alloc(borrow_signatures);
// for ((s, _), sig) in borrow_signatures.iter() {
// for ((s, _), sig) in borrow_signatures.procs.iter() {
// dbg!((s, sig));
// }
@ -58,10 +58,8 @@ pub fn insert_inc_dec_operations<'a>(
}
}
/**
Enum indicating whether a symbol should be reference counted or not.
This includes layouts that themselves can be stack allocated but that contain a heap allocated item.
*/
/// Enum indicating whether a symbol should be reference counted or not.
/// This includes layouts that themselves can be stack allocated but that contain a heap allocated item.
#[derive(Copy, Clone)]
enum VarRcType {
ReferenceCounted,
@ -435,6 +433,7 @@ fn insert_inc_dec_operations_proc<'a>(
// Add all arguments to the environment (if they are reference counted)
let borrow_signature = borrow_signatures
.procs
.get(&(proc.name.name(), proc.proc_layout(arena)))
.unwrap();
for ((_, symbol), ownership) in proc.args.iter().zip(borrow_signature.iter()) {
@ -1008,10 +1007,6 @@ fn insert_refcount_operations_binding<'a>(
ret_layout,
..
} => {
// let new_let = new_let!(stmt);
//
// inc_owned!(arguments.iter().copied(), new_let)
let proc_layout = ProcLayout {
arguments: arg_layouts,
result: ret_layout,
@ -1020,6 +1015,7 @@ fn insert_refcount_operations_binding<'a>(
let borrow_signature = match environment
.borrow_signatures
.procs
.get(&(name.name(), proc_layout))
{
Some(s) => s,

View File

@ -29,7 +29,8 @@ const TEST_WRAPPER_NAME: &str = "test_wrapper";
#[allow(dead_code)]
pub const OPT_LEVEL: OptLevel = if cfg!(debug_assertions) {
OptLevel::Normal
// OptLevel::Normal
OptLevel::Optimize
} else {
OptLevel::Optimize
};

View File

@ -51,7 +51,7 @@ procedure Test.11 (#Derived_gen.10, #Derived_gen.11):
joinpoint Test.27 Test.12 #Attr.12:
let Test.34 : Int1 = UnionAtIndex (Id 2) (Index 1) #Attr.12;
let Test.33 : [<rnw><null>, C *self Int1, C *self Int1] = UnionAtIndex (Id 2) (Index 0) #Attr.12;
joinpoint #Derived_gen.16:
joinpoint #Derived_gen.14:
joinpoint Test.31 Test.29:
let Test.30 : U8 = GetTagId Test.33;
switch Test.30:
@ -78,16 +78,15 @@ procedure Test.11 (#Derived_gen.10, #Derived_gen.11):
jump Test.31 Test.32;
in
let #Derived_gen.17 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if #Derived_gen.17 then
let #Derived_gen.15 : Int1 = lowlevel RefCountIsUnique #Attr.12;
if #Derived_gen.15 then
free #Attr.12;
jump #Derived_gen.16;
jump #Derived_gen.14;
else
inc Test.33;
decref #Attr.12;
jump #Derived_gen.16;
jump #Derived_gen.14;
in
inc #Derived_gen.10;
jump Test.27 #Derived_gen.10 #Derived_gen.11;
procedure Test.2 (Test.13):
@ -144,7 +143,6 @@ procedure Test.9 (Test.10, #Attr.12):
default:
let Test.41 : Str = CallByName Test.11 Test.10 Test.42;
dec Test.10;
jump Test.40 Test.41;
in
@ -180,6 +178,5 @@ procedure Test.0 ():
default:
let Test.17 : Str = CallByName Test.11 Test.18 Test.16;
dec Test.18;
ret Test.17;

View File

@ -128,7 +128,6 @@ procedure List.92 (#Derived_gen.29, #Derived_gen.30, #Derived_gen.31, #Derived_g
ret List.164;
in
inc #Derived_gen.29;
inc #Derived_gen.30;
jump List.603 #Derived_gen.29 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33;
procedure List.92 (#Derived_gen.37, #Derived_gen.38, #Derived_gen.39, #Derived_gen.40, #Derived_gen.41):
@ -146,7 +145,6 @@ procedure List.92 (#Derived_gen.37, #Derived_gen.38, #Derived_gen.39, #Derived_g
ret List.164;
in
inc #Derived_gen.37;
inc #Derived_gen.38;
jump List.577 #Derived_gen.37 #Derived_gen.38 #Derived_gen.39 #Derived_gen.40 #Derived_gen.41;
procedure Num.127 (#Attr.2):
@ -235,7 +233,6 @@ procedure Test.67 (Test.68, Test.262, Test.66):
let Test.69 : List U8 = CallByName Test.3 Test.68 Test.290 Test.291;
let Test.265 : {} = Struct {};
let Test.264 : List U8 = CallByName List.18 Test.66 Test.69 Test.265;
dec Test.69;
ret Test.264;
procedure Test.67 (Test.68, Test.262, Test.66):
@ -244,7 +241,6 @@ procedure Test.67 (Test.68, Test.262, Test.66):
let Test.69 : List U8 = CallByName Test.3 Test.68 Test.322 Test.323;
let Test.297 : {} = Struct {};
let Test.296 : List U8 = CallByName List.18 Test.66 Test.69 Test.297;
dec Test.69;
ret Test.296;
procedure Test.70 (Test.71, Test.266):

View File

@ -85,7 +85,6 @@ procedure List.92 (#Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.14;
inc #Derived_gen.13;
jump List.577 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17;
@ -171,7 +170,6 @@ procedure Test.67 (Test.68, Test.261, Test.66):
let Test.69 : List U8 = CallByName Test.3 Test.68 Test.289 Test.290;
let Test.264 : {} = Struct {};
let Test.263 : List U8 = CallByName List.18 Test.66 Test.69 Test.264;
dec Test.69;
ret Test.263;
procedure Test.70 (Test.71, Test.265):

View File

@ -93,7 +93,6 @@ procedure List.92 (#Derived_gen.17, #Derived_gen.18, #Derived_gen.19, #Derived_g
ret List.164;
in
inc #Derived_gen.17;
inc #Derived_gen.18;
jump List.577 #Derived_gen.17 #Derived_gen.18 #Derived_gen.19 #Derived_gen.20 #Derived_gen.21;
procedure Num.127 (#Attr.2):
@ -178,7 +177,6 @@ procedure Test.67 (Test.68, Test.262, Test.66):
let Test.69 : List U8 = CallByName Test.3 Test.68 Test.290 Test.291;
let Test.265 : {} = Struct {};
let Test.264 : List U8 = CallByName List.18 Test.66 Test.69 Test.265;
dec Test.69;
ret Test.264;
procedure Test.70 (Test.71, Test.266):

View File

@ -90,7 +90,6 @@ procedure List.92 (#Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.14;
inc #Derived_gen.13;
jump List.577 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17;
@ -192,7 +191,6 @@ procedure Test.60 (Test.61, Test.266, #Attr.12):
let Test.62 : List U8 = CallByName Test.3 Test.61 Test.274 Test.275;
let Test.268 : List U8 = CallByName List.18 Test.58 Test.62 Test.59;
dec Test.58;
dec Test.62;
ret Test.268;
procedure Test.63 (Test.64, Test.65, Test.59):

View File

@ -93,7 +93,6 @@ procedure List.92 (#Derived_gen.14, #Derived_gen.15, #Derived_gen.16, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.15;
inc #Derived_gen.14;
jump List.577 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17 #Derived_gen.18;
@ -195,7 +194,6 @@ procedure Test.60 (Test.61, Test.267, #Attr.12):
let Test.62 : List U8 = CallByName Test.3 Test.61 Test.275 Test.276;
let Test.269 : List U8 = CallByName List.18 Test.58 Test.62 Test.59;
dec Test.58;
dec Test.62;
ret Test.269;
procedure Test.63 (Test.64, Test.65, Test.59):

View File

@ -141,7 +141,6 @@ procedure Dict.38 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.
let Dict.766 : U32 = CallByName Num.131 Dict.236;
let Dict.752 : {U32, U32} = Struct {Dict.766, Dict.224};
let Dict.237 : List {U32, U32} = CallByName Dict.67 Dict.221 Dict.752 Dict.223;
dec Dict.221;
let Dict.751 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.237, Dict.235, Dict.227, Dict.228, Dict.229};
ret Dict.751;
else
@ -150,8 +149,6 @@ procedure Dict.38 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.
let Dict.239 : U32 = CallByName Dict.48 Dict.224;
jump Dict.736 Dict.221 Dict.222 Dict.238 Dict.239 Dict.225 Dict.226 Dict.227 Dict.228 Dict.229;
in
inc #Derived_gen.0;
inc #Derived_gen.1;
inc #Derived_gen.4;
jump Dict.736 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4 #Derived_gen.5 #Derived_gen.6 #Derived_gen.7 #Derived_gen.8;
@ -232,7 +229,6 @@ procedure Dict.59 (Dict.719):
let Dict.381 : List {U32, U32} = StructAtIndex 0 Dict.855;
let Dict.382 : U64 = StructAtIndex 1 Dict.855;
let Dict.383 : List {U32, U32} = CallByName Dict.64 Dict.381 Dict.376 Dict.380;
dec Dict.381;
let Dict.837 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = Struct {Dict.383, Dict.376, Dict.382, Dict.378, Dict.380};
ret Dict.837;
else
@ -324,7 +320,6 @@ procedure Dict.67 (#Derived_gen.28, #Derived_gen.29, #Derived_gen.30):
let Dict.754 : List {U32, U32} = CallByName List.3 Dict.414 Dict.416 Dict.415;
ret Dict.754;
in
inc #Derived_gen.28;
jump Dict.753 #Derived_gen.28 #Derived_gen.29 #Derived_gen.30;
procedure Dict.68 (Dict.419, Dict.420):
@ -422,8 +417,6 @@ procedure Dict.8 (Dict.210, Dict.211, Dict.212):
let Dict.219 : U32 = CallByName Dict.70 Dict.218;
let Dict.220 : U64 = CallByName Dict.71 Dict.218 Dict.217;
let Dict.735 : {List {U32, U32}, List {Str, I64}, U64, Float32, U8} = CallByName Dict.38 Dict.213 Dict.214 Dict.220 Dict.219 Dict.211 Dict.212 Dict.215 Dict.216 Dict.217;
dec Dict.214;
dec Dict.213;
dec Dict.211;
ret Dict.735;
in
@ -900,7 +893,6 @@ procedure Inspect.60 (Inspect.298):
procedure List.11 (List.138, List.139):
let List.636 : List {U32, U32} = CallByName List.68 List.139;
let List.635 : List {U32, U32} = CallByName List.90 List.138 List.139 List.636;
dec List.636;
ret List.635;
procedure List.18 (List.160, List.161, List.162):
@ -1011,7 +1003,6 @@ procedure List.90 (#Derived_gen.33, #Derived_gen.34, #Derived_gen.35):
else
ret List.142;
in
inc #Derived_gen.35;
jump List.625 #Derived_gen.33 #Derived_gen.34 #Derived_gen.35;
procedure List.92 (#Derived_gen.50, #Derived_gen.51, #Derived_gen.52, #Derived_gen.53, #Derived_gen.54):
@ -1055,7 +1046,6 @@ procedure List.93 (#Derived_gen.23, #Derived_gen.24, #Derived_gen.25, #Derived_g
let List.622 : {Str, I64} = CallByName List.66 List.172 List.175;
inc List.622;
let List.177 : List {U32, U32} = CallByName Dict.398 List.173 List.622 List.175 List.174;
dec List.173;
let List.621 : U64 = 1i64;
let List.620 : U64 = CallByName Num.51 List.175 List.621;
jump List.616 List.172 List.177 List.174 List.620 List.176;
@ -1063,7 +1053,6 @@ procedure List.93 (#Derived_gen.23, #Derived_gen.24, #Derived_gen.25, #Derived_g
dec List.172;
ret List.173;
in
inc #Derived_gen.24;
inc #Derived_gen.23;
jump List.616 #Derived_gen.23 #Derived_gen.24 #Derived_gen.25 #Derived_gen.26 #Derived_gen.27;

View File

@ -34,7 +34,6 @@ procedure Inspect.202 (Inspect.203, #Attr.12):
let Inspect.321 : Str = CallByName Inspect.59 Inspect.333 Inspect.335;
dec Inspect.335;
let Inspect.317 : Str = CallByName Inspect.204 Inspect.321 Inspect.336;
dec Inspect.321;
dec Inspect.336;
let Inspect.318 : Str = ")";
let Inspect.316 : Str = CallByName Inspect.59 Inspect.317 Inspect.318;
@ -168,7 +167,6 @@ procedure List.92 (#Derived_gen.10, #Derived_gen.11, #Derived_gen.12, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.11;
inc #Derived_gen.10;
jump List.577 #Derived_gen.10 #Derived_gen.11 #Derived_gen.12 #Derived_gen.13 #Derived_gen.14;

View File

@ -37,7 +37,6 @@ procedure Inspect.202 (Inspect.203, #Attr.12):
let Inspect.321 : Str = CallByName Inspect.59 Inspect.333 Inspect.335;
dec Inspect.335;
let Inspect.317 : Str = CallByName Inspect.204 Inspect.321 Inspect.336;
dec Inspect.321;
dec Inspect.336;
let Inspect.318 : Str = ")";
let Inspect.316 : Str = CallByName Inspect.59 Inspect.317 Inspect.318;
@ -171,7 +170,6 @@ procedure List.92 (#Derived_gen.13, #Derived_gen.14, #Derived_gen.15, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.14;
inc #Derived_gen.13;
jump List.577 #Derived_gen.13 #Derived_gen.14 #Derived_gen.15 #Derived_gen.16 #Derived_gen.17;

View File

@ -23,14 +23,12 @@ procedure Test.1 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2):
let Test.20 : I64 = 1i64;
let Test.19 : I64 = CallByName Num.20 Test.5 Test.20;
let Test.16 : List I64 = CallByName Test.1 Test.6 Test.3 Test.19;
dec Test.6;
let Test.18 : I64 = 1i64;
let Test.17 : I64 = CallByName Num.19 Test.5 Test.18;
jump Test.12 Test.16 Test.17 Test.4;
else
ret Test.2;
in
inc #Derived_gen.0;
jump Test.12 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2;
procedure Test.0 ():
@ -38,5 +36,4 @@ procedure Test.0 ():
let Test.10 : I64 = 0i64;
let Test.11 : I64 = 0i64;
let Test.8 : List I64 = CallByName Test.1 Test.9 Test.10 Test.11;
dec Test.9;
ret Test.8;

View File

@ -80,7 +80,6 @@ procedure List.92 (#Derived_gen.0, #Derived_gen.1, #Derived_gen.2, #Derived_gen.
ret List.164;
in
inc #Derived_gen.0;
inc #Derived_gen.1;
jump List.577 #Derived_gen.0 #Derived_gen.1 #Derived_gen.2 #Derived_gen.3 #Derived_gen.4;
procedure Num.127 (#Attr.2):
@ -196,7 +195,6 @@ procedure Test.63 (Test.64, Test.276, #Attr.12):
let Test.65 : List U8 = CallByName Test.4 Test.64 Test.284 Test.285;
let Test.278 : List U8 = CallByName List.18 Test.61 Test.65 Test.62;
dec Test.61;
dec Test.65;
ret Test.278;
procedure Test.66 (Test.67, Test.68, Test.62):

View File

@ -156,7 +156,6 @@ procedure List.92 (#Derived_gen.29, #Derived_gen.30, #Derived_gen.31, #Derived_g
ret List.164;
in
inc #Derived_gen.29;
inc #Derived_gen.30;
jump List.577 #Derived_gen.29 #Derived_gen.30 #Derived_gen.31 #Derived_gen.32 #Derived_gen.33;
procedure List.92 (#Derived_gen.52, #Derived_gen.53, #Derived_gen.54, #Derived_gen.55, #Derived_gen.56):
@ -173,7 +172,6 @@ procedure List.92 (#Derived_gen.52, #Derived_gen.53, #Derived_gen.54, #Derived_g
dec List.163;
ret List.164;
in
inc #Derived_gen.53;
inc #Derived_gen.52;
jump List.604 #Derived_gen.52 #Derived_gen.53 #Derived_gen.54 #Derived_gen.55 #Derived_gen.56;
@ -323,7 +321,6 @@ procedure Test.63 (Test.64, Test.279, #Attr.12):
let Test.65 : List U8 = CallByName Test.4 Test.64 Test.331 Test.332;
let Test.325 : List U8 = CallByName List.18 Test.61 Test.65 Test.62;
dec Test.61;
dec Test.65;
ret Test.325;
procedure Test.63 (Test.64, Test.279, #Attr.12):
@ -334,7 +331,6 @@ procedure Test.63 (Test.64, Test.279, #Attr.12):
let Test.65 : List U8 = CallByName Test.4 Test.64 Test.287 Test.288;
let Test.281 : List U8 = CallByName List.18 Test.61 Test.65 Test.62;
dec Test.61;
dec Test.65;
ret Test.281;
procedure Test.66 (Test.67, Test.68, Test.62):

View File

@ -1286,6 +1286,7 @@ writeIndents = \buf, indents ->
|> Str.concat indent
|> writeIndents (indents - 1)
writeTagImpls : Str, List { name : Str, payload : [Some TypeId, None] }, Str, U64, (Str, [Some TypeId, None] -> Str) -> Str
writeTagImpls = \buf, tags, discriminantName, indents, f ->
buf
|> writeIndents indents

View File

@ -566,3 +566,22 @@ fn freeing_boxes() {
"#
));
}
#[test]
fn joinpoint_that_owns() {
valgrind_test(indoc!(
r#"
(
writeIndents = \buf, indents ->
if indents <= 0 then
buf
else
buf
|> Str.concat " "
|> writeIndents (indents - 1)
List.walk [{}, {}] "" \accum, {} -> accum |> writeIndents 4
)
"#
));
}