mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 16:21:11 +00:00
First pass update erasure IR
This commit is contained in:
parent
7ea85e44d2
commit
dc56a0ffef
4 changed files with 128 additions and 151 deletions
|
@ -4091,7 +4091,7 @@ impl<'a> ProcLayout<'a> {
|
|||
arguments
|
||||
} else {
|
||||
let mut extended_args = Vec::with_capacity_in(arguments.len(), arena);
|
||||
extended_args.extend(arguments.iter().chain(&[Layout::OPAQUE_PTR]).copied());
|
||||
extended_args.extend(arguments.iter().chain(&[Layout::ERASED]).copied());
|
||||
extended_args.into_bump_slice()
|
||||
};
|
||||
|
||||
|
|
|
@ -4,30 +4,26 @@ use roc_types::subs::Variable;
|
|||
|
||||
use crate::{
|
||||
borrow::Ownership,
|
||||
layout::{ErasedIndex, FunctionPointer, InLayout, LambdaName, Layout, LayoutCache, LayoutRepr},
|
||||
layout::{FunctionPointer, InLayout, LambdaName, Layout, LayoutCache, LayoutRepr},
|
||||
};
|
||||
|
||||
use super::{
|
||||
with_hole, BranchInfo, Call, CallType, CapturedSymbols, Env, Expr, JoinPointId, Param, Procs,
|
||||
Stmt, UpdateModeId,
|
||||
with_hole, BranchInfo, Call, CallType, CapturedSymbols, Env, ErasedField, Expr, JoinPointId,
|
||||
Param, Procs, Stmt, UpdateModeId,
|
||||
};
|
||||
|
||||
const ERASED_FUNCTION_FIELD_LAYOUTS: &[InLayout] =
|
||||
&[Layout::OPAQUE_PTR, Layout::OPAQUE_PTR, Layout::OPAQUE_PTR];
|
||||
|
||||
fn index_erased_function<'a>(
|
||||
arena: &'a Bump,
|
||||
assign_to: Symbol,
|
||||
erased_function: Symbol,
|
||||
index: ErasedIndex,
|
||||
field: ErasedField,
|
||||
) -> impl FnOnce(Stmt<'a>) -> Stmt<'a> {
|
||||
move |rest| {
|
||||
Stmt::Let(
|
||||
assign_to,
|
||||
Expr::StructAtIndex {
|
||||
index: index as _,
|
||||
structure: erased_function,
|
||||
field_layouts: ERASED_FUNCTION_FIELD_LAYOUTS,
|
||||
Expr::ErasedLoad {
|
||||
symbol: erased_function,
|
||||
field,
|
||||
},
|
||||
Layout::OPAQUE_PTR,
|
||||
arena.alloc(rest),
|
||||
|
@ -153,30 +149,30 @@ pub fn call_erased_function<'a>(
|
|||
|
||||
let join_point_id = JoinPointId(env.unique_symbol());
|
||||
|
||||
// f_value = f.value
|
||||
// f_value = ErasedLoad(f, .value)
|
||||
let f_value = env.unique_symbol();
|
||||
let let_f_value = index_erased_function(arena, f_value, f, ErasedIndex::Value);
|
||||
let let_f_value = index_erased_function(arena, f_value, f, ErasedField::Value);
|
||||
|
||||
// f_callee = f.callee
|
||||
// f_callee = ErasedLoad(f, .callee)
|
||||
let f_callee = env.unique_symbol();
|
||||
let let_f_callee = index_erased_function(arena, f_callee, f, ErasedIndex::Callee);
|
||||
let let_f_callee = index_erased_function(arena, f_callee, f, ErasedField::Callee);
|
||||
|
||||
let mut build_closure_data_branch = |env: &mut Env, pass_closure| {
|
||||
// f_callee = cast(f_callee, (..params) -> ret);
|
||||
// f_callee = Cast(f_callee, (..params) -> ret);
|
||||
// result = f_callee ..args
|
||||
// jump join result
|
||||
|
||||
let (f_args, function_argument_symbols) = if pass_closure {
|
||||
// f_args = ...args, f.value
|
||||
// f_args = ...args, f
|
||||
// function_argument_symbols = ...args, f.value
|
||||
let f_args = {
|
||||
let mut args = AVec::with_capacity_in(f_args.len() + 1, arena);
|
||||
args.extend(f_args.iter().chain(&[Layout::OPAQUE_PTR]).copied());
|
||||
args.extend(f_args.iter().chain(&[Layout::ERASED]).copied());
|
||||
args.into_bump_slice()
|
||||
};
|
||||
let function_argument_symbols = {
|
||||
let mut args = AVec::with_capacity_in(function_argument_symbols.len() + 1, arena);
|
||||
args.extend(function_argument_symbols.iter().chain(&[f_value]));
|
||||
args.extend(function_argument_symbols.iter().chain(&[f]));
|
||||
args.into_bump_slice()
|
||||
};
|
||||
(f_args, function_argument_symbols)
|
||||
|
@ -239,9 +235,9 @@ pub fn call_erased_function<'a>(
|
|||
};
|
||||
|
||||
let remainder =
|
||||
// f_value = f.value
|
||||
// f_value = ErasedLoad(f, .value)
|
||||
let_f_value(
|
||||
// f_callee = f.callee
|
||||
// f_callee = ErasedLoad(f, .callee)
|
||||
let_f_callee(
|
||||
//
|
||||
call_and_jump_on_value,
|
||||
|
@ -302,33 +298,27 @@ pub fn build_erased_function<'a>(
|
|||
assigned: Symbol,
|
||||
hole: &'a Stmt<'a>,
|
||||
) -> Stmt<'a> {
|
||||
let value = env.unique_symbol();
|
||||
let callee = env.unique_symbol();
|
||||
let refcounter = env.unique_symbol();
|
||||
|
||||
// assigned = Expr::Struct({ value, callee, refcounter })
|
||||
// hole <assigned>
|
||||
let result = Stmt::Let(
|
||||
assigned,
|
||||
Expr::Struct(env.arena.alloc([value, callee, refcounter])),
|
||||
Layout::ERASED,
|
||||
hole,
|
||||
);
|
||||
|
||||
// refcounter = TODO
|
||||
// <hole>
|
||||
let result = Stmt::Let(
|
||||
refcounter,
|
||||
Expr::NullPointer,
|
||||
Layout::OPAQUE_PTR,
|
||||
env.arena.alloc(result),
|
||||
);
|
||||
|
||||
let ResolvedErasedLambda {
|
||||
captures,
|
||||
lambda_name,
|
||||
} = resolved_lambda;
|
||||
|
||||
let value = match captures {
|
||||
None => None,
|
||||
Some(_) => Some(env.unique_symbol()),
|
||||
};
|
||||
|
||||
let callee = env.unique_symbol();
|
||||
|
||||
// assigned = Expr::ErasedMake({ value, callee })
|
||||
// hole <assigned>
|
||||
let result = Stmt::Let(
|
||||
assigned,
|
||||
Expr::ErasedMake { value, callee },
|
||||
Layout::ERASED,
|
||||
hole,
|
||||
);
|
||||
|
||||
// callee = Expr::FunctionPointer(f)
|
||||
let result = Stmt::Let(
|
||||
callee,
|
||||
|
@ -339,16 +329,7 @@ pub fn build_erased_function<'a>(
|
|||
|
||||
// value = Expr::Box({s})
|
||||
match captures {
|
||||
None => {
|
||||
// value = nullptr
|
||||
// <hole>
|
||||
Stmt::Let(
|
||||
value,
|
||||
Expr::NullPointer,
|
||||
Layout::OPAQUE_PTR,
|
||||
env.arena.alloc(result),
|
||||
)
|
||||
}
|
||||
None => result,
|
||||
Some(ResolvedErasedCaptures { layouts, symbols }) => {
|
||||
// captures = {...captures}
|
||||
// captures = Box(captures)
|
||||
|
@ -364,7 +345,7 @@ pub fn build_erased_function<'a>(
|
|||
layout_cache.put_in_direct_no_semantic(LayoutRepr::Boxed(stack_captures_layout));
|
||||
|
||||
let result = Stmt::Let(
|
||||
value,
|
||||
value.unwrap(),
|
||||
Expr::Call(Call {
|
||||
call_type: CallType::LowLevel {
|
||||
op: LowLevel::PtrCast,
|
||||
|
@ -473,6 +454,7 @@ pub fn unpack_closure_data<'a>(
|
|||
captures: &[(Symbol, Variable)],
|
||||
mut hole: Stmt<'a>,
|
||||
) -> Stmt<'a> {
|
||||
let loaded_captures = env.unique_symbol();
|
||||
let heap_captures = env.unique_symbol();
|
||||
let stack_captures = env.unique_symbol();
|
||||
|
||||
|
@ -525,5 +507,12 @@ pub fn unpack_closure_data<'a>(
|
|||
env.arena.alloc(hole),
|
||||
);
|
||||
|
||||
hole
|
||||
let let_loaded_captures = index_erased_function(
|
||||
env.arena,
|
||||
loaded_captures,
|
||||
captures_symbol,
|
||||
ErasedField::Value,
|
||||
);
|
||||
|
||||
let_loaded_captures(hole)
|
||||
}
|
||||
|
|
|
@ -1413,7 +1413,7 @@ impl<'a> ClosureDataKind<'a> {
|
|||
pub fn data_layout(&self) -> InLayout<'a> {
|
||||
match self {
|
||||
Self::LambdaSet(lambda_set) => lambda_set.full_layout,
|
||||
Self::Erased => Layout::OPAQUE_PTR,
|
||||
Self::Erased => Layout::ERASED,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2603,14 +2603,6 @@ impl<'a> Layout<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Index into an [Erased layout][Layout::ERASED].
|
||||
#[repr(u8)]
|
||||
pub(crate) enum ErasedIndex {
|
||||
Value = 0,
|
||||
Callee = 1,
|
||||
RefCounter = 2,
|
||||
}
|
||||
|
||||
impl<'a> LayoutRepr<'a> {
|
||||
pub const UNIT: Self = LayoutRepr::struct_(&[]);
|
||||
pub const BOOL: Self = LayoutRepr::Builtin(Builtin::Bool);
|
||||
|
|
|
@ -13,101 +13,97 @@ main = (f "") {}
|
|||
# ^^^^ {} -?-> Str
|
||||
|
||||
# -emit:mono
|
||||
procedure : `#UserApp.3` Str
|
||||
procedure = `#UserApp.3` (`#UserApp.40`: {}):
|
||||
let `#UserApp.41` : Str = "";
|
||||
ret `#UserApp.41`;
|
||||
procedure Bool.2 ():
|
||||
let Bool.23 : Int1 = true;
|
||||
ret Bool.23;
|
||||
|
||||
procedure : `#UserApp.4` Str
|
||||
procedure = `#UserApp.4` (`#UserApp.29`: {}, `#Attr.#arg_closure`: Boxed([])):
|
||||
let `#UserApp.31` : Boxed({Str}) = lowlevel PtrCast `#Attr.#arg_closure`;
|
||||
let `#UserApp.32` : {Str} = Unbox `#UserApp.31`;
|
||||
joinpoint `#Derived_gen.IdentId(0)`:
|
||||
let `#UserApp.s` : Str = StructAtIndex 0 `#UserApp.32`;
|
||||
ret `#UserApp.s`;
|
||||
in
|
||||
let `#Derived_gen.IdentId(1)` : Int1 = lowlevel RefCountIsUnique `#UserApp.31`;
|
||||
if `#Derived_gen.IdentId(1)` then
|
||||
decref `#UserApp.31`;
|
||||
jump `#Derived_gen.IdentId(0)`;
|
||||
procedure Test.1 (Test.2):
|
||||
let Test.38 : Int1 = CallByName Bool.2;
|
||||
if Test.38 then
|
||||
dec Test.2;
|
||||
let Test.44 : {} = Struct {};
|
||||
let Test.45 : Boxed({}) = Box Test.44;
|
||||
let Test.42 : Boxed([]) = lowlevel PtrCast Test.45;
|
||||
let Test.43 : Boxed([]) = FunctionPointer Test.3;
|
||||
dec Test.43;
|
||||
let Test.39 : ?Erased = ErasedMake { value: Test.42, callee: Test.43 };
|
||||
ret Test.39;
|
||||
else
|
||||
inc `#UserApp.32`;
|
||||
decref `#UserApp.31`;
|
||||
jump `#Derived_gen.IdentId(0)`;
|
||||
let Test.36 : {Str} = Struct {Test.2};
|
||||
let Test.37 : Boxed({Str}) = Box Test.36;
|
||||
let Test.34 : Boxed([]) = lowlevel PtrCast Test.37;
|
||||
let Test.35 : Boxed([]) = FunctionPointer Test.4;
|
||||
dec Test.35;
|
||||
let Test.28 : ?Erased = ErasedMake { value: Test.34, callee: Test.35 };
|
||||
ret Test.28;
|
||||
|
||||
procedure : `#UserApp.f` {Boxed([]), Boxed([]), Boxed([])}
|
||||
procedure = `#UserApp.f` (`#UserApp.s`: Str):
|
||||
let `#UserApp.38` : Int1 = CallByName `Bool.true`;
|
||||
if `#UserApp.38` then
|
||||
dec `#UserApp.s`;
|
||||
let `#UserApp.45` : {} = Struct {};
|
||||
let `#UserApp.46` : Boxed({}) = Box `#UserApp.45`;
|
||||
let `#UserApp.42` : Boxed([]) = lowlevel PtrCast `#UserApp.46`;
|
||||
let `#UserApp.43` : Boxed([]) = FunctionPointer `#UserApp.3`;
|
||||
let `#UserApp.44` : Boxed([]) = NullPointer;
|
||||
let `#UserApp.39` : {Boxed([]), Boxed([]), Boxed([])} = Struct {`#UserApp.42`, `#UserApp.43`, `#UserApp.44`};
|
||||
ret `#UserApp.39`;
|
||||
else
|
||||
let `#UserApp.36` : {Str} = Struct {`#UserApp.s`};
|
||||
let `#UserApp.37` : Boxed({Str}) = Box `#UserApp.36`;
|
||||
let `#UserApp.33` : Boxed([]) = lowlevel PtrCast `#UserApp.37`;
|
||||
let `#UserApp.34` : Boxed([]) = FunctionPointer `#UserApp.4`;
|
||||
let `#UserApp.35` : Boxed([]) = NullPointer;
|
||||
let `#UserApp.28` : {Boxed([]), Boxed([]), Boxed([])} = Struct {`#UserApp.33`, `#UserApp.34`, `#UserApp.35`};
|
||||
ret `#UserApp.28`;
|
||||
procedure Test.3 (Test.40):
|
||||
let Test.41 : Str = "";
|
||||
ret Test.41;
|
||||
|
||||
procedure : `Bool.true` Int1
|
||||
procedure = `Bool.true` ():
|
||||
let `Bool.23` : Int1 = true;
|
||||
ret `Bool.23`;
|
||||
|
||||
procedure : `#UserApp.main` Str
|
||||
procedure = `#UserApp.main` ():
|
||||
let `#UserApp.6` : {} = Struct {};
|
||||
let `#UserApp.17` : Str = "";
|
||||
let `#UserApp.47` : Boxed([]) = NullPointer;
|
||||
let `#UserApp.48` : Boxed([]) = FunctionPointer `#UserApp.f`;
|
||||
let `#UserApp.49` : Boxed([]) = NullPointer;
|
||||
let `#UserApp.18` : {Boxed([]), Boxed([]), Boxed([])} = Struct {`#UserApp.47`, `#UserApp.48`, `#UserApp.49`};
|
||||
joinpoint `#UserApp.19` `#UserApp.7`:
|
||||
joinpoint `#UserApp.8` `#UserApp.5`:
|
||||
ret `#UserApp.5`;
|
||||
procedure Test.4 (Test.29, #Attr.12):
|
||||
inc #Attr.12;
|
||||
let Test.31 : Boxed([]) = ErasedLoad #Attr.12 .Value;
|
||||
dec Test.31;
|
||||
let Test.32 : Boxed({Str}) = lowlevel PtrCast #Attr.12;
|
||||
let Test.33 : {Str} = Unbox Test.32;
|
||||
joinpoint #Derived_gen.0:
|
||||
let Test.2 : Str = StructAtIndex 0 Test.33;
|
||||
ret Test.2;
|
||||
in
|
||||
let `#UserApp.9` : Boxed([]) = StructAtIndex 0 `#UserApp.7`;
|
||||
let `#UserApp.10` : Boxed([]) = StructAtIndex 1 `#UserApp.7`;
|
||||
let `#Derived_gen.IdentId(4)` : Boxed([]) = StructAtIndex 2 `#UserApp.7`;
|
||||
dec `#Derived_gen.IdentId(4)`;
|
||||
let `#UserApp.12` : Boxed([]) = NullPointer;
|
||||
let `#UserApp.11` : Int1 = lowlevel Eq `#UserApp.9` `#UserApp.12`;
|
||||
dec `#UserApp.12`;
|
||||
switch `#UserApp.11`:
|
||||
let #Derived_gen.1 : Int1 = lowlevel RefCountIsUnique Test.32;
|
||||
if #Derived_gen.1 then
|
||||
free Test.32;
|
||||
jump #Derived_gen.0;
|
||||
else
|
||||
inc Test.33;
|
||||
decref Test.32;
|
||||
jump #Derived_gen.0;
|
||||
|
||||
procedure Test.0 ():
|
||||
let Test.6 : {} = Struct {};
|
||||
let Test.17 : Str = "";
|
||||
let Test.46 : Boxed([]) = FunctionPointer Test.1;
|
||||
dec Test.46;
|
||||
let Test.18 : ?Erased = ErasedMake { value: <null>, callee: Test.46 };
|
||||
joinpoint Test.19 Test.7:
|
||||
joinpoint Test.8 Test.5:
|
||||
ret Test.5;
|
||||
in
|
||||
let Test.9 : Boxed([]) = ErasedLoad Test.7 .Value;
|
||||
let Test.10 : Boxed([]) = ErasedLoad Test.7 .Callee;
|
||||
let Test.12 : Boxed([]) = NullPointer;
|
||||
let Test.11 : Int1 = lowlevel Eq Test.9 Test.12;
|
||||
dec Test.12;
|
||||
dec Test.9;
|
||||
switch Test.11:
|
||||
case 0:
|
||||
dec `#UserApp.9`;
|
||||
let `#UserApp.13` : FunPtr({} -> Str) = lowlevel PtrCast `#UserApp.10`;
|
||||
let `#UserApp.14` : Str = CallByPtr `#UserApp.13` `#UserApp.6`;
|
||||
jump `#UserApp.8` `#UserApp.14`;
|
||||
let Test.13 : FunPtr({} -> Str) = lowlevel PtrCast Test.10;
|
||||
let Test.14 : Str = CallByPtr Test.13 Test.6;
|
||||
jump Test.8 Test.14;
|
||||
|
||||
default:
|
||||
let `#UserApp.15` : FunPtr({}, Boxed([]) -> Str) = lowlevel PtrCast `#UserApp.10`;
|
||||
let `#UserApp.16` : Str = CallByPtr `#UserApp.15` `#UserApp.6` `#UserApp.9`;
|
||||
jump `#UserApp.8` `#UserApp.16`;
|
||||
inc Test.7;
|
||||
let Test.15 : FunPtr({}, ?Erased -> Str) = lowlevel PtrCast Test.10;
|
||||
let Test.16 : Str = CallByPtr Test.15 Test.6 Test.7;
|
||||
jump Test.8 Test.16;
|
||||
|
||||
in
|
||||
let `#UserApp.20` : Boxed([]) = StructAtIndex 0 `#UserApp.18`;
|
||||
let `#UserApp.21` : Boxed([]) = StructAtIndex 1 `#UserApp.18`;
|
||||
dec `#UserApp.49`;
|
||||
let `#UserApp.23` : Boxed([]) = NullPointer;
|
||||
let `#UserApp.22` : Int1 = lowlevel Eq `#UserApp.20` `#UserApp.23`;
|
||||
dec `#UserApp.23`;
|
||||
switch `#UserApp.22`:
|
||||
let Test.20 : Boxed([]) = ErasedLoad Test.18 .Value;
|
||||
let Test.21 : Boxed([]) = ErasedLoad Test.18 .Callee;
|
||||
let Test.23 : Boxed([]) = NullPointer;
|
||||
let Test.22 : Int1 = lowlevel Eq Test.20 Test.23;
|
||||
dec Test.20;
|
||||
dec Test.23;
|
||||
switch Test.22:
|
||||
case 0:
|
||||
dec `#UserApp.20`;
|
||||
let `#UserApp.24` : FunPtr(Str -> {Boxed([]), Boxed([]), Boxed([])}) = lowlevel PtrCast `#UserApp.21`;
|
||||
let `#UserApp.25` : {Boxed([]), Boxed([]), Boxed([])} = CallByPtr `#UserApp.24` `#UserApp.17`;
|
||||
jump `#UserApp.19` `#UserApp.25`;
|
||||
let Test.24 : FunPtr(Str -> ?Erased) = lowlevel PtrCast Test.21;
|
||||
let Test.25 : ?Erased = CallByPtr Test.24 Test.17;
|
||||
jump Test.19 Test.25;
|
||||
|
||||
default:
|
||||
let `#UserApp.26` : FunPtr(Str, Boxed([]) -> {Boxed([]), Boxed([]), Boxed([])}) = lowlevel PtrCast `#UserApp.21`;
|
||||
let `#UserApp.27` : {Boxed([]), Boxed([]), Boxed([])} = CallByPtr `#UserApp.26` `#UserApp.17` `#UserApp.20`;
|
||||
jump `#UserApp.19` `#UserApp.27`;
|
||||
inc Test.18;
|
||||
let Test.26 : FunPtr(Str, ?Erased -> ?Erased) = lowlevel PtrCast Test.21;
|
||||
let Test.27 : ?Erased = CallByPtr Test.26 Test.17 Test.18;
|
||||
jump Test.19 Test.27;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue