Update dev and wasm backend to use new list bitcode args

This commit is contained in:
Brendan Hansknecht 2024-04-09 21:57:40 -07:00
parent c79febb52d
commit d5e91ed61e
No known key found for this signature in database
GPG key ID: 0EA784685083E75B
5 changed files with 479 additions and 140 deletions

View file

@ -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

View file

@ -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,