From 12a330dd7603145608f8829cc56ec2db507a4571 Mon Sep 17 00:00:00 2001 From: Brian Carroll Date: Fri, 31 Dec 2021 08:34:04 +0000 Subject: [PATCH] Refactor to move all refcount IR gen to the same file --- compiler/mono/src/code_gen_help/mod.rs | 75 +-------------------- compiler/mono/src/code_gen_help/refcount.rs | 73 +++++++++++++++++++- 2 files changed, 75 insertions(+), 73 deletions(-) diff --git a/compiler/mono/src/code_gen_help/mod.rs b/compiler/mono/src/code_gen_help/mod.rs index e62a9a5265..b1f399e6d7 100644 --- a/compiler/mono/src/code_gen_help/mod.rs +++ b/compiler/mono/src/code_gen_help/mod.rs @@ -6,7 +6,7 @@ use roc_module::low_level::LowLevel; use roc_module::symbol::{IdentIds, ModuleId, Symbol}; use crate::ir::{ - Call, CallSpecId, CallType, Expr, HostExposedLayouts, Literal, ModifyRc, Proc, ProcLayout, + Call, CallSpecId, CallType, Expr, HostExposedLayouts, ModifyRc, Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId, }; use crate::layout::{Builtin, Layout, UnionLayout}; @@ -129,83 +129,14 @@ impl<'a> CodeGenHelp<'a> { return (following, Vec::new_in(self.arena)); } - let arena = self.arena; - let mut ctx = Context { new_linker_data: Vec::new_in(self.arena), recursive_union: None, op: HelperOp::from(modify), }; - match modify { - ModifyRc::Inc(structure, amount) => { - let layout_isize = self.layout_isize; - - // Define a constant for the amount to increment - let amount_sym = self.create_symbol(ident_ids, "amount"); - let amount_expr = Expr::Literal(Literal::Int(*amount as i128)); - let amount_stmt = |next| Stmt::Let(amount_sym, amount_expr, layout_isize, next); - - // Call helper proc, passing the Roc structure and constant amount - let call_result_empty = self.create_symbol(ident_ids, "call_result_empty"); - let call_expr = self - .call_specialized_op( - ident_ids, - &mut ctx, - layout, - arena.alloc([*structure, amount_sym]), - ) - .unwrap(); - let call_stmt = Stmt::Let(call_result_empty, call_expr, LAYOUT_UNIT, following); - let rc_stmt = arena.alloc(amount_stmt(arena.alloc(call_stmt))); - - (rc_stmt, ctx.new_linker_data) - } - - ModifyRc::Dec(structure) => { - // Call helper proc, passing the Roc structure - let call_result_empty = self.create_symbol(ident_ids, "call_result_empty"); - let call_expr = self - .call_specialized_op(ident_ids, &mut ctx, layout, arena.alloc([*structure])) - .unwrap(); - - let rc_stmt = arena.alloc(Stmt::Let( - call_result_empty, - call_expr, - LAYOUT_UNIT, - following, - )); - - (rc_stmt, ctx.new_linker_data) - } - - ModifyRc::DecRef(structure) => { - // No generated procs for DecRef, just lowlevel ops - let rc_ptr_sym = self.create_symbol(ident_ids, "rc_ptr"); - - // Pass the refcount pointer to the lowlevel call (see utils.zig) - let call_result_empty = self.create_symbol(ident_ids, "call_result_empty"); - let call_expr = Expr::Call(Call { - call_type: CallType::LowLevel { - op: LowLevel::RefCountDec, - update_mode: UpdateModeId::BACKEND_DUMMY, - }, - arguments: arena.alloc([rc_ptr_sym]), - }); - let call_stmt = Stmt::Let(call_result_empty, call_expr, LAYOUT_UNIT, following); - - // FIXME: `structure` is a pointer to the stack, not the heap! - let rc_stmt = arena.alloc(refcount::rc_ptr_from_data_ptr( - self, - ident_ids, - *structure, - rc_ptr_sym, - arena.alloc(call_stmt), - )); - - (rc_stmt, ctx.new_linker_data) - } - } + let rc_stmt = refcount::refcount_stmt(self, ident_ids, &mut ctx, layout, modify, following); + (self.arena.alloc(rc_stmt), ctx.new_linker_data) } /// Replace a generic `Lowlevel::Eq` call with a specialized helper proc. diff --git a/compiler/mono/src/code_gen_help/refcount.rs b/compiler/mono/src/code_gen_help/refcount.rs index b81dc84082..aa56898734 100644 --- a/compiler/mono/src/code_gen_help/refcount.rs +++ b/compiler/mono/src/code_gen_help/refcount.rs @@ -4,7 +4,7 @@ use roc_module::symbol::{IdentIds, Symbol}; use crate::code_gen_help::let_lowlevel; use crate::ir::{ - BranchInfo, Call, CallType, Expr, JoinPointId, Literal, Param, Stmt, UpdateModeId, + BranchInfo, Call, CallType, Expr, JoinPointId, Literal, ModifyRc, Param, Stmt, UpdateModeId, }; use crate::layout::{Builtin, Layout, UnionLayout}; @@ -18,6 +18,77 @@ const LAYOUT_U32: Layout = Layout::Builtin(Builtin::Int(IntWidth::U32)); const ARG_1: Symbol = Symbol::ARG_1; const ARG_2: Symbol = Symbol::ARG_2; +pub fn refcount_stmt<'a>( + root: &mut CodeGenHelp<'a>, + ident_ids: &mut IdentIds, + ctx: &mut Context<'a>, + layout: Layout<'a>, + modify: &ModifyRc, + following: &'a Stmt<'a>, +) -> Stmt<'a> { + let arena = root.arena; + + match modify { + ModifyRc::Inc(structure, amount) => { + let layout_isize = root.layout_isize; + + // Define a constant for the amount to increment + let amount_sym = root.create_symbol(ident_ids, "amount"); + let amount_expr = Expr::Literal(Literal::Int(*amount as i128)); + let amount_stmt = |next| Stmt::Let(amount_sym, amount_expr, layout_isize, next); + + // Call helper proc, passing the Roc structure and constant amount + let call_result_empty = root.create_symbol(ident_ids, "call_result_empty"); + let call_expr = root + .call_specialized_op( + ident_ids, + ctx, + layout, + arena.alloc([*structure, amount_sym]), + ) + .unwrap(); + + let call_stmt = Stmt::Let(call_result_empty, call_expr, LAYOUT_UNIT, following); + amount_stmt(arena.alloc(call_stmt)) + } + + ModifyRc::Dec(structure) => { + // Call helper proc, passing the Roc structure + let call_result_empty = root.create_symbol(ident_ids, "call_result_empty"); + let call_expr = root + .call_specialized_op(ident_ids, ctx, layout, arena.alloc([*structure])) + .unwrap(); + + Stmt::Let(call_result_empty, call_expr, LAYOUT_UNIT, following) + } + + ModifyRc::DecRef(structure) => { + // No generated procs for DecRef, just lowlevel ops + let rc_ptr_sym = root.create_symbol(ident_ids, "rc_ptr"); + + // Pass the refcount pointer to the lowlevel call (see utils.zig) + let call_result_empty = root.create_symbol(ident_ids, "call_result_empty"); + let call_expr = Expr::Call(Call { + call_type: CallType::LowLevel { + op: LowLevel::RefCountDec, + update_mode: UpdateModeId::BACKEND_DUMMY, + }, + arguments: arena.alloc([rc_ptr_sym]), + }); + let call_stmt = Stmt::Let(call_result_empty, call_expr, LAYOUT_UNIT, following); + + // FIXME: `structure` is a pointer to the stack, not the heap! + rc_ptr_from_data_ptr( + root, + ident_ids, + *structure, + rc_ptr_sym, + arena.alloc(call_stmt), + ) + } + } +} + pub fn refcount_generic<'a>( root: &mut CodeGenHelp<'a>, ident_ids: &mut IdentIds,