mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Merge branch 'main' into drop_specialization
Signed-off-by: J Teeuwissen <jelleteeuwissen@hotmail.nl>
This commit is contained in:
commit
7439ee0c8c
229 changed files with 3602 additions and 2412 deletions
|
@ -1031,7 +1031,7 @@ pub fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[Ownership] {
|
|||
unreachable!("These lowlevel operations are turned into mono Expr's")
|
||||
}
|
||||
|
||||
PtrCast | RefCountInc | RefCountDec | RefCountIsUnique => {
|
||||
PtrCast | PtrWrite | RefCountInc | RefCountDec | RefCountIsUnique => {
|
||||
unreachable!("Only inserted *after* borrow checking: {:?}", op);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,8 @@ use roc_module::symbol::{IdentIds, ModuleId, Symbol};
|
|||
use roc_target::TargetInfo;
|
||||
|
||||
use crate::ir::{
|
||||
Call, CallSpecId, CallType, Expr, HostExposedLayouts, JoinPointId, ModifyRc, Proc, ProcLayout,
|
||||
SelfRecursive, Stmt, UpdateModeId,
|
||||
Call, CallSpecId, CallType, Expr, HostExposedLayouts, JoinPointId, ModifyRc, PassedFunction,
|
||||
Proc, ProcLayout, SelfRecursive, Stmt, UpdateModeId,
|
||||
};
|
||||
use crate::layout::{
|
||||
Builtin, InLayout, LambdaName, Layout, LayoutInterner, Niche, STLayoutInterner, UnionLayout,
|
||||
|
@ -21,6 +21,7 @@ const LAYOUT_UNIT: InLayout = Layout::UNIT;
|
|||
|
||||
const ARG_1: Symbol = Symbol::ARG_1;
|
||||
const ARG_2: Symbol = Symbol::ARG_2;
|
||||
const ARG_3: Symbol = Symbol::ARG_3;
|
||||
|
||||
/// "Infinite" reference count, for static values
|
||||
/// Ref counts are encoded as negative numbers where isize::MIN represents 1
|
||||
|
@ -584,6 +585,175 @@ impl<'a> CodeGenHelp<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct CallerProc<'a> {
|
||||
pub proc_symbol: Symbol,
|
||||
pub proc_layout: ProcLayout<'a>,
|
||||
pub proc: Proc<'a>,
|
||||
}
|
||||
|
||||
impl<'a> CallerProc<'a> {
|
||||
fn create_symbol(home: ModuleId, ident_ids: &mut IdentIds, debug_name: &str) -> Symbol {
|
||||
let ident_id = ident_ids.add_str(debug_name);
|
||||
Symbol::new(home, ident_id)
|
||||
}
|
||||
|
||||
fn create_caller_proc_symbol(
|
||||
home: ModuleId,
|
||||
ident_ids: &mut IdentIds,
|
||||
operation: &str,
|
||||
wrapped_function: Symbol,
|
||||
) -> Symbol {
|
||||
let debug_name = format!("#help_{}_{}_{:?}", "caller", operation, wrapped_function,);
|
||||
|
||||
Self::create_symbol(home, ident_ids, &debug_name)
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
arena: &'a Bump,
|
||||
home: ModuleId,
|
||||
ident_ids: &mut IdentIds,
|
||||
layout_interner: &mut STLayoutInterner<'a>,
|
||||
passed_function: &PassedFunction<'a>,
|
||||
capture_layout: Option<InLayout<'a>>,
|
||||
) -> Self {
|
||||
let mut ctx = Context {
|
||||
new_linker_data: Vec::new_in(arena),
|
||||
recursive_union: None,
|
||||
op: HelperOp::Eq,
|
||||
};
|
||||
|
||||
let box_capture_layout = if let Some(capture_layout) = capture_layout {
|
||||
layout_interner.insert(Layout::Boxed(capture_layout))
|
||||
} else {
|
||||
layout_interner.insert(Layout::Boxed(Layout::UNIT))
|
||||
};
|
||||
|
||||
let box_argument_layout =
|
||||
layout_interner.insert(Layout::Boxed(passed_function.argument_layouts[0]));
|
||||
|
||||
let box_return_layout =
|
||||
layout_interner.insert(Layout::Boxed(passed_function.return_layout));
|
||||
|
||||
let proc_layout = ProcLayout {
|
||||
arguments: arena.alloc([box_capture_layout, box_argument_layout, box_return_layout]),
|
||||
result: Layout::UNIT,
|
||||
niche: Niche::NONE,
|
||||
};
|
||||
|
||||
let proc_symbol =
|
||||
Self::create_caller_proc_symbol(home, ident_ids, "map", passed_function.name.name());
|
||||
|
||||
ctx.new_linker_data.push((proc_symbol, proc_layout));
|
||||
|
||||
let unbox_capture = Expr::ExprUnbox {
|
||||
symbol: Symbol::ARG_1,
|
||||
};
|
||||
|
||||
let unbox_argument = Expr::ExprUnbox {
|
||||
symbol: Symbol::ARG_2,
|
||||
};
|
||||
|
||||
let unboxed_capture = Self::create_symbol(home, ident_ids, "unboxed_capture");
|
||||
let unboxed_argument = Self::create_symbol(home, ident_ids, "unboxed_argument");
|
||||
let call_result = Self::create_symbol(home, ident_ids, "call_result");
|
||||
let unit_symbol = Self::create_symbol(home, ident_ids, "unit_symbol");
|
||||
let ignored = Self::create_symbol(home, ident_ids, "ignored");
|
||||
|
||||
let call = Expr::Call(Call {
|
||||
call_type: CallType::ByName {
|
||||
name: passed_function.name,
|
||||
ret_layout: passed_function.return_layout,
|
||||
arg_layouts: passed_function.argument_layouts,
|
||||
specialization_id: passed_function.specialization_id,
|
||||
},
|
||||
arguments: if capture_layout.is_some() {
|
||||
arena.alloc([unboxed_argument, unboxed_capture])
|
||||
} else {
|
||||
arena.alloc([unboxed_argument])
|
||||
},
|
||||
});
|
||||
|
||||
let ptr_write = Expr::Call(Call {
|
||||
call_type: CallType::LowLevel {
|
||||
op: LowLevel::PtrWrite,
|
||||
update_mode: UpdateModeId::BACKEND_DUMMY,
|
||||
},
|
||||
arguments: arena.alloc([Symbol::ARG_3, call_result]),
|
||||
});
|
||||
|
||||
let mut body = Stmt::Let(
|
||||
unboxed_argument,
|
||||
unbox_argument,
|
||||
passed_function.argument_layouts[0],
|
||||
arena.alloc(Stmt::Let(
|
||||
call_result,
|
||||
call,
|
||||
passed_function.return_layout,
|
||||
arena.alloc(Stmt::Let(
|
||||
ignored,
|
||||
ptr_write,
|
||||
box_return_layout,
|
||||
arena.alloc(Stmt::Let(
|
||||
unit_symbol,
|
||||
Expr::Struct(&[]),
|
||||
Layout::UNIT,
|
||||
arena.alloc(Stmt::Ret(unit_symbol)),
|
||||
)),
|
||||
)),
|
||||
)),
|
||||
);
|
||||
|
||||
if let Some(capture_layout) = capture_layout {
|
||||
body = Stmt::Let(
|
||||
unboxed_capture,
|
||||
unbox_capture,
|
||||
capture_layout,
|
||||
arena.alloc(body),
|
||||
);
|
||||
}
|
||||
|
||||
let args: &'a [(InLayout<'a>, Symbol)] = {
|
||||
arena.alloc([
|
||||
(box_capture_layout, ARG_1),
|
||||
(box_argument_layout, ARG_2),
|
||||
(box_return_layout, ARG_3),
|
||||
])
|
||||
};
|
||||
|
||||
let proc = Proc {
|
||||
name: LambdaName::no_niche(proc_symbol),
|
||||
args,
|
||||
body,
|
||||
closure_data_layout: None,
|
||||
ret_layout: Layout::UNIT,
|
||||
is_self_recursive: SelfRecursive::NotSelfRecursive,
|
||||
host_exposed_layouts: HostExposedLayouts::NotHostExposed,
|
||||
};
|
||||
|
||||
if false {
|
||||
let allocator = ven_pretty::BoxAllocator;
|
||||
let doc = proc
|
||||
.to_doc::<_, (), _>(
|
||||
&allocator,
|
||||
layout_interner,
|
||||
true,
|
||||
crate::ir::Parens::NotNeeded,
|
||||
)
|
||||
.1
|
||||
.pretty(80)
|
||||
.to_string();
|
||||
|
||||
println!("{}", doc);
|
||||
}
|
||||
|
||||
Self {
|
||||
proc_symbol,
|
||||
proc_layout,
|
||||
proc,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn let_lowlevel<'a>(
|
||||
arena: &'a Bump,
|
||||
result_layout: InLayout<'a>,
|
||||
|
|
|
@ -25,9 +25,9 @@ use crate::{
|
|||
/**
|
||||
Insert the reference count operations for procedures.
|
||||
*/
|
||||
pub fn insert_inc_dec_operations<'a, 'i>(
|
||||
pub fn insert_inc_dec_operations<'a>(
|
||||
arena: &'a Bump,
|
||||
layout_interner: &'i STLayoutInterner<'a>,
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
procedures: &mut HashMap<(Symbol, ProcLayout), Proc<'a>, BuildHasherDefault<WyHash>>,
|
||||
) {
|
||||
// Create a SymbolRcTypesEnv for the procedures as they get referenced but should be marked as non reference counted.
|
||||
|
@ -401,9 +401,9 @@ impl<'v> RefcountEnvironment<'v> {
|
|||
/**
|
||||
Insert the reference counting operations into a statement.
|
||||
*/
|
||||
fn insert_inc_dec_operations_proc<'a, 'i>(
|
||||
fn insert_inc_dec_operations_proc<'a>(
|
||||
arena: &'a Bump,
|
||||
mut symbol_rc_types_env: SymbolRcTypesEnv<'a, 'i>,
|
||||
mut symbol_rc_types_env: SymbolRcTypesEnv<'a, '_>,
|
||||
proc: &mut Proc<'a>,
|
||||
) {
|
||||
// Clone the symbol_rc_types_env and insert the symbols in the current procedure.
|
||||
|
|
|
@ -282,8 +282,9 @@ impl AbilityAliases {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
|
||||
pub enum CapturedSymbols<'a> {
|
||||
#[default]
|
||||
None,
|
||||
Captured(&'a [(Symbol, Variable)]),
|
||||
}
|
||||
|
@ -297,12 +298,6 @@ impl<'a> CapturedSymbols<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Default for CapturedSymbols<'a> {
|
||||
fn default() -> Self {
|
||||
CapturedSymbols::None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct Proc<'a> {
|
||||
pub name: LambdaName<'a>,
|
||||
|
@ -2725,8 +2720,8 @@ fn patterns_to_when<'a>(
|
|||
/// { x } -> body
|
||||
///
|
||||
/// conversion of one-pattern when expressions will do the most optimal thing
|
||||
fn pattern_to_when<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
fn pattern_to_when(
|
||||
env: &mut Env<'_, '_>,
|
||||
pattern_var: Variable,
|
||||
pattern: Loc<roc_can::pattern::Pattern>,
|
||||
body_var: Variable,
|
||||
|
@ -5743,8 +5738,8 @@ fn compile_struct_like<'a, L, UnusedLayout>(
|
|||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn late_resolve_ability_specialization<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
fn late_resolve_ability_specialization(
|
||||
env: &mut Env<'_, '_>,
|
||||
member: Symbol,
|
||||
specialization_id: Option<SpecializationId>,
|
||||
specialization_var: Variable,
|
||||
|
|
|
@ -1193,7 +1193,7 @@ fn extract<'a>(
|
|||
|
||||
/// FIND IRRELEVANT BRANCHES
|
||||
|
||||
fn is_irrelevant_to<'a>(selected_path: &[PathInstruction], branch: &Branch<'a>) -> bool {
|
||||
fn is_irrelevant_to(selected_path: &[PathInstruction], branch: &Branch<'_>) -> bool {
|
||||
match branch
|
||||
.patterns
|
||||
.iter()
|
||||
|
@ -1720,7 +1720,7 @@ fn test_to_comparison<'a>(
|
|||
|
||||
Test::IsFloat(test_int, precision) => {
|
||||
// TODO maybe we can actually use i64 comparison here?
|
||||
let test_float = f64::from_bits(test_int as u64);
|
||||
let test_float = f64::from_bits(test_int);
|
||||
let lhs = Expr::Literal(Literal::Float(test_float));
|
||||
let lhs_symbol = env.unique_symbol();
|
||||
stores.push((lhs_symbol, Layout::float_width(precision), lhs));
|
||||
|
@ -2240,7 +2240,7 @@ fn decide_to_branching<'a>(
|
|||
|
||||
let tag = match test {
|
||||
Test::IsInt(v, _) => i128::from_ne_bytes(v) as u64,
|
||||
Test::IsFloat(v, _) => v as u64,
|
||||
Test::IsFloat(v, _) => v,
|
||||
Test::IsBit(v) => v as u64,
|
||||
Test::IsByte { tag_id, .. } => tag_id as u64,
|
||||
Test::IsCtor { tag_id, .. } => tag_id as u64,
|
||||
|
|
|
@ -457,7 +457,7 @@ macro_rules! cached {
|
|||
}
|
||||
|
||||
pub type TagIdIntType = u16;
|
||||
pub const MAX_ENUM_SIZE: usize = (std::mem::size_of::<TagIdIntType>() * 8) as usize;
|
||||
pub const MAX_ENUM_SIZE: usize = std::mem::size_of::<TagIdIntType>() * 8;
|
||||
const GENERATE_NULLABLE: bool = true;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
|
@ -898,7 +898,7 @@ impl<'a> UnionLayout<'a> {
|
|||
} => {
|
||||
debug_assert_ne!(nullable_id, tag_id != 0);
|
||||
|
||||
other_fields[index as usize]
|
||||
other_fields[index]
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ macro_rules! cache_interned_layouts {
|
|||
)*
|
||||
}
|
||||
|
||||
fn fill_reserved_layouts<'a>(interner: &mut STLayoutInterner<'a>) {
|
||||
fn fill_reserved_layouts(interner: &mut STLayoutInterner<'_>) {
|
||||
assert!(interner.is_empty());
|
||||
$(
|
||||
interner.insert($layout);
|
||||
|
@ -433,6 +433,22 @@ impl<'a> InLayout<'a> {
|
|||
pub fn index(&self) -> usize {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn try_int_width(self) -> Option<IntWidth> {
|
||||
match self {
|
||||
Layout::U8 => Some(IntWidth::U8),
|
||||
Layout::U16 => Some(IntWidth::U16),
|
||||
Layout::U32 => Some(IntWidth::U32),
|
||||
Layout::U64 => Some(IntWidth::U64),
|
||||
Layout::U128 => Some(IntWidth::U128),
|
||||
Layout::I8 => Some(IntWidth::I8),
|
||||
Layout::I16 => Some(IntWidth::I16),
|
||||
Layout::I32 => Some(IntWidth::I32),
|
||||
Layout::I64 => Some(IntWidth::I64),
|
||||
Layout::I128 => Some(IntWidth::I128),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A concurrent interner, suitable for usage between threads.
|
||||
|
|
|
@ -1128,8 +1128,8 @@ impl<'a> ReuseEnvironment<'a> {
|
|||
/**
|
||||
Check if a layout can be reused. by verifying if the layout is a union and if the tag is not nullable.
|
||||
*/
|
||||
fn can_reuse_layout<'a, 'i>(
|
||||
layout_interner: &'i STLayoutInterner<'a>,
|
||||
fn can_reuse_layout<'a>(
|
||||
layout_interner: &STLayoutInterner<'a>,
|
||||
environment: &ReuseEnvironment<'a>,
|
||||
layout: &InLayout<'a>,
|
||||
) -> Reuse {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue