mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 05:49:08 +00:00
Update dev and wasm backend to use new list bitcode args
This commit is contained in:
parent
c79febb52d
commit
d5e91ed61e
5 changed files with 479 additions and 140 deletions
|
@ -34,8 +34,10 @@ pub const REFCOUNT_MAX: usize = 0;
|
|||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
pub enum HelperOp {
|
||||
Inc,
|
||||
IncN,
|
||||
Dec,
|
||||
IndirectInc,
|
||||
IndirectIncN,
|
||||
IndirectDec,
|
||||
DecRef(JoinPointId),
|
||||
Reset,
|
||||
|
@ -53,7 +55,7 @@ impl HelperOp {
|
|||
}
|
||||
|
||||
fn is_inc(&self) -> bool {
|
||||
matches!(self, Self::Inc)
|
||||
matches!(self, Self::Inc | Self::IncN)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +140,7 @@ impl<'a> CodeGenHelp<'a> {
|
|||
following: &'a Stmt<'a>,
|
||||
) -> (&'a Stmt<'a>, Vec<'a, (Symbol, ProcLayout<'a>)>) {
|
||||
let op = match modify {
|
||||
ModifyRc::Inc(..) => HelperOp::Inc,
|
||||
ModifyRc::Inc(..) => HelperOp::IncN,
|
||||
ModifyRc::Dec(_) => HelperOp::Dec,
|
||||
ModifyRc::DecRef(_) => {
|
||||
let jp_decref = JoinPointId(self.create_symbol(ident_ids, "jp_decref"));
|
||||
|
@ -310,9 +312,11 @@ impl<'a> CodeGenHelp<'a> {
|
|||
match ctx.op {
|
||||
Dec | DecRef(_) => (LAYOUT_UNIT, self.arena.alloc([arg])),
|
||||
Reset | ResetRef => (layout, self.arena.alloc([layout])),
|
||||
Inc => (LAYOUT_UNIT, self.arena.alloc([arg, self.layout_isize])),
|
||||
Inc => (LAYOUT_UNIT, self.arena.alloc([arg])),
|
||||
IncN => (LAYOUT_UNIT, self.arena.alloc([arg, self.layout_isize])),
|
||||
IndirectDec => (LAYOUT_UNIT, arena.alloc([ptr_arg])),
|
||||
IndirectInc => (LAYOUT_UNIT, arena.alloc([ptr_arg, self.layout_isize])),
|
||||
IndirectIncN => (LAYOUT_UNIT, arena.alloc([ptr_arg, self.layout_isize])),
|
||||
IndirectInc => (LAYOUT_UNIT, arena.alloc([ptr_arg])),
|
||||
Eq => (LAYOUT_BOOL, self.arena.alloc([arg, arg])),
|
||||
}
|
||||
};
|
||||
|
@ -375,7 +379,7 @@ impl<'a> CodeGenHelp<'a> {
|
|||
|
||||
// Recursively generate the body of the Proc and sub-procs
|
||||
let (ret_layout, body) = match ctx.op {
|
||||
Inc | Dec | DecRef(_) => (
|
||||
Inc | IncN | Dec | DecRef(_) => (
|
||||
LAYOUT_UNIT,
|
||||
refcount::refcount_generic(
|
||||
self,
|
||||
|
@ -386,7 +390,7 @@ impl<'a> CodeGenHelp<'a> {
|
|||
Symbol::ARG_1,
|
||||
),
|
||||
),
|
||||
IndirectInc | IndirectDec => (
|
||||
IndirectInc | IndirectIncN | IndirectDec => (
|
||||
LAYOUT_UNIT,
|
||||
refcount::refcount_indirect(
|
||||
self,
|
||||
|
@ -428,18 +432,18 @@ impl<'a> CodeGenHelp<'a> {
|
|||
let args: &'a [(InLayout<'a>, Symbol)] = {
|
||||
let roc_value = (layout, ARG_1);
|
||||
match ctx.op {
|
||||
Inc => {
|
||||
IncN => {
|
||||
let inc_amount = (self.layout_isize, ARG_2);
|
||||
self.arena.alloc([roc_value, inc_amount])
|
||||
}
|
||||
Dec | DecRef(_) | Reset | ResetRef => self.arena.alloc([roc_value]),
|
||||
IndirectInc => {
|
||||
Inc | Dec | DecRef(_) | Reset | ResetRef => self.arena.alloc([roc_value]),
|
||||
IndirectIncN => {
|
||||
let ptr_layout =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(layout));
|
||||
let inc_amount = (self.layout_isize, ARG_2);
|
||||
self.arena.alloc([(ptr_layout, ARG_1), inc_amount])
|
||||
}
|
||||
IndirectDec => {
|
||||
IndirectInc | IndirectDec => {
|
||||
let ptr_layout =
|
||||
layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(layout));
|
||||
self.arena.alloc([(ptr_layout, ARG_1)])
|
||||
|
@ -478,17 +482,17 @@ impl<'a> CodeGenHelp<'a> {
|
|||
let proc_symbol: Symbol = self.create_symbol(ident_ids, &debug_name);
|
||||
|
||||
let proc_layout = match ctx.op {
|
||||
HelperOp::Inc => ProcLayout {
|
||||
HelperOp::IncN => ProcLayout {
|
||||
arguments: self.arena.alloc([layout, self.layout_isize]),
|
||||
result: LAYOUT_UNIT,
|
||||
niche: Niche::NONE,
|
||||
},
|
||||
HelperOp::Dec => ProcLayout {
|
||||
HelperOp::Dec | HelperOp::Inc => ProcLayout {
|
||||
arguments: self.arena.alloc([layout]),
|
||||
result: LAYOUT_UNIT,
|
||||
niche: Niche::NONE,
|
||||
},
|
||||
HelperOp::IndirectInc => {
|
||||
HelperOp::IndirectIncN => {
|
||||
let ptr_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(layout));
|
||||
|
||||
ProcLayout {
|
||||
|
@ -497,7 +501,7 @@ impl<'a> CodeGenHelp<'a> {
|
|||
niche: Niche::NONE,
|
||||
}
|
||||
}
|
||||
HelperOp::IndirectDec => {
|
||||
HelperOp::IndirectDec | HelperOp::IndirectInc => {
|
||||
let ptr_layout = layout_interner.insert_direct_no_semantic(LayoutRepr::Ptr(layout));
|
||||
|
||||
ProcLayout {
|
||||
|
@ -1021,7 +1025,10 @@ fn layout_needs_helper_proc<'a>(
|
|||
// Str type can use either Zig functions or generated IR, since it's not generic.
|
||||
// Eq uses a Zig function, refcount uses generated IR.
|
||||
// Both are fine, they were just developed at different times.
|
||||
matches!(op, HelperOp::Inc | HelperOp::Dec | HelperOp::DecRef(_))
|
||||
matches!(
|
||||
op,
|
||||
HelperOp::Inc | HelperOp::IncN | HelperOp::Dec | HelperOp::DecRef(_)
|
||||
)
|
||||
}
|
||||
LayoutRepr::Builtin(Builtin::List(_)) => true,
|
||||
LayoutRepr::Struct { .. } => true, // note: we do generate a helper for Unit, with just a Stmt::Ret
|
||||
|
|
|
@ -139,6 +139,7 @@ pub fn refcount_indirect<'a>(
|
|||
|
||||
let indirect_op = ctx.op;
|
||||
let direct_op = match ctx.op {
|
||||
HelperOp::IndirectIncN => HelperOp::IncN,
|
||||
HelperOp::IndirectInc => HelperOp::Inc,
|
||||
HelperOp::IndirectDec => HelperOp::Dec,
|
||||
_ => unreachable!(),
|
||||
|
@ -568,7 +569,7 @@ fn rc_return_stmt<'a>(
|
|||
}
|
||||
|
||||
fn refcount_args<'a>(root: &CodeGenHelp<'a>, ctx: &Context<'a>, structure: Symbol) -> &'a [Symbol] {
|
||||
if ctx.op == HelperOp::Inc {
|
||||
if ctx.op == HelperOp::IncN {
|
||||
// second argument is always `amount`, passed down through the call stack
|
||||
root.arena.alloc([structure, Symbol::ARG_2])
|
||||
} else {
|
||||
|
@ -681,6 +682,33 @@ fn modify_refcount<'a>(
|
|||
let zig_call_result = root.create_symbol(ident_ids, "zig_call_result");
|
||||
match ctx.op {
|
||||
HelperOp::Inc => {
|
||||
let layout_isize = root.layout_isize;
|
||||
|
||||
let (op, ptr) = match ptr {
|
||||
Pointer::ToData(s) => (LowLevel::RefCountIncDataPtr, s),
|
||||
Pointer::ToRefcount(s) => (LowLevel::RefCountIncRcPtr, s),
|
||||
};
|
||||
|
||||
let amount_sym = root.create_symbol(ident_ids, "amount");
|
||||
let amount_expr = Expr::Literal(Literal::Int(1_i128.to_ne_bytes()));
|
||||
let amount_stmt = |next| Stmt::Let(amount_sym, amount_expr, layout_isize, next);
|
||||
|
||||
let zig_call_expr = Expr::Call(Call {
|
||||
call_type: CallType::LowLevel {
|
||||
op,
|
||||
update_mode: UpdateModeId::BACKEND_DUMMY,
|
||||
},
|
||||
arguments: root.arena.alloc([ptr, amount_sym]),
|
||||
});
|
||||
let zig_call_stmt = Stmt::Let(zig_call_result, zig_call_expr, LAYOUT_UNIT, following);
|
||||
|
||||
amount_stmt(root.arena.alloc(
|
||||
//
|
||||
zig_call_stmt,
|
||||
))
|
||||
}
|
||||
|
||||
HelperOp::IncN => {
|
||||
let (op, ptr) = match ptr {
|
||||
Pointer::ToData(s) => (LowLevel::RefCountIncDataPtr, s),
|
||||
Pointer::ToRefcount(s) => (LowLevel::RefCountIncRcPtr, s),
|
||||
|
@ -708,6 +736,18 @@ fn modify_refcount<'a>(
|
|||
let alignment_expr = Expr::Literal(Literal::Int((alignment as i128).to_ne_bytes()));
|
||||
let alignment_stmt = |next| Stmt::Let(alignment_sym, alignment_expr, LAYOUT_U32, next);
|
||||
|
||||
// This function is not used for lits, so this is always false.
|
||||
let elements_refcounted_sym = root.create_symbol(ident_ids, "elements_refcounted");
|
||||
let elements_refcounted_expr = Expr::Literal(Literal::Bool(false));
|
||||
let elements_refcounted_stmt = |next| {
|
||||
Stmt::Let(
|
||||
elements_refcounted_sym,
|
||||
elements_refcounted_expr,
|
||||
LAYOUT_BOOL,
|
||||
next,
|
||||
)
|
||||
};
|
||||
|
||||
let zig_call_expr = Expr::Call(Call {
|
||||
call_type: CallType::LowLevel {
|
||||
op,
|
||||
|
@ -717,10 +757,10 @@ fn modify_refcount<'a>(
|
|||
});
|
||||
let zig_call_stmt = Stmt::Let(zig_call_result, zig_call_expr, LAYOUT_UNIT, following);
|
||||
|
||||
alignment_stmt(root.arena.alloc(
|
||||
alignment_stmt(root.arena.alloc(elements_refcounted_stmt(root.arena.alloc(
|
||||
//
|
||||
zig_call_stmt,
|
||||
))
|
||||
))))
|
||||
}
|
||||
|
||||
_ => unreachable!(),
|
||||
|
@ -907,6 +947,9 @@ fn refcount_str<'a>(
|
|||
))
|
||||
}
|
||||
|
||||
// TODO: This needs to be updated.
|
||||
// It probably can just generate a call to `list.incref/decref` from zig bitcode.
|
||||
// That said, not sure how to generate a pass along function pointers here.
|
||||
fn refcount_list<'a>(
|
||||
root: &mut CodeGenHelp<'a>,
|
||||
ident_ids: &mut IdentIds,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue