Describe how a enum lambda set should be switched in the representation

This commit is contained in:
Ayaz Hafiz 2022-08-10 10:20:56 -07:00
parent f5e3105b37
commit a93735473a
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
2 changed files with 43 additions and 48 deletions

View file

@ -1,8 +1,8 @@
#![allow(clippy::manual_map)] #![allow(clippy::manual_map)]
use crate::layout::{ use crate::layout::{
Builtin, CapturesNiche, ClosureCallOptions, ClosureRepresentation, LambdaName, LambdaSet, Builtin, CapturesNiche, ClosureCallOptions, ClosureRepresentation, EnumDispatch, LambdaName,
Layout, LayoutCache, LayoutProblem, RawFunctionLayout, TagIdIntType, UnionLayout, LambdaSet, Layout, LayoutCache, LayoutProblem, RawFunctionLayout, TagIdIntType, UnionLayout,
WrappedVariant, WrappedVariant,
}; };
use bumpalo::collections::{CollectIn, Vec}; use bumpalo::collections::{CollectIn, Vec};
@ -3269,23 +3269,10 @@ fn specialize_external<'a>(
); );
} }
ClosureRepresentation::MultiDispatch(layout) => match layout { ClosureRepresentation::EnumDispatch(_) => {
Layout::Builtin(Builtin::Bool) => { // just ignore this value, since it's not a capture
// just ignore this value, since it's not a capture // IDEA don't pass this value in the future
// IDEA don't pass this value in the future }
}
Layout::Builtin(Builtin::Int(IntWidth::U8)) => {
// just ignore this value, since it's not a capture
// IDEA don't pass this value in the future
}
other => {
// NOTE other values always should be wrapped in a 1-element record
unreachable!(
"{:?} is not a valid closure data representation",
other
)
}
},
} }
} }
(None, CapturedSymbols::None) | (None, CapturedSymbols::Captured([])) => {} (None, CapturedSymbols::None) | (None, CapturedSymbols::Captured([])) => {}
@ -5448,8 +5435,8 @@ where
hole, hole,
) )
} }
ClosureRepresentation::MultiDispatch(layout) => match layout { ClosureRepresentation::EnumDispatch(repr) => match repr {
Layout::Builtin(Builtin::Bool) => { EnumDispatch::Bool => {
debug_assert_eq!(symbols.len(), 0); debug_assert_eq!(symbols.len(), 0);
debug_assert_eq!(lambda_set.set.len(), 2); debug_assert_eq!(lambda_set.set.len(), 2);
@ -5458,7 +5445,7 @@ where
Stmt::Let(assigned, expr, lambda_set_layout, hole) Stmt::Let(assigned, expr, lambda_set_layout, hole)
} }
Layout::Builtin(Builtin::Int(IntWidth::U8)) => { EnumDispatch::U8 => {
debug_assert_eq!(symbols.len(), 0); debug_assert_eq!(symbols.len(), 0);
debug_assert!(lambda_set.set.len() > 2); debug_assert!(lambda_set.set.len() > 2);
@ -5471,9 +5458,6 @@ where
Stmt::Let(assigned, expr, lambda_set_layout, hole) Stmt::Let(assigned, expr, lambda_set_layout, hole)
} }
layout => {
internal_error!("Invalid layout for multi-dispatch closure: {:?}", layout)
}
}, },
}; };
@ -9228,8 +9212,8 @@ where
build_call(env, call, assigned, return_layout, env.arena.alloc(hole)) build_call(env, call, assigned, return_layout, env.arena.alloc(hole))
} }
ClosureCallOptions::MultiDispatch(layout) => match layout { ClosureCallOptions::EnumDispatch(repr) => match repr {
Layout::Builtin(Builtin::Bool) => { EnumDispatch::Bool => {
let closure_tag_id_symbol = closure_data_symbol; let closure_tag_id_symbol = closure_data_symbol;
lowlevel_enum_lambda_set_to_switch( lowlevel_enum_lambda_set_to_switch(
@ -9245,7 +9229,7 @@ where
hole, hole,
) )
} }
Layout::Builtin(Builtin::Int(IntWidth::U8)) => { EnumDispatch::U8 => {
let closure_tag_id_symbol = closure_data_symbol; let closure_tag_id_symbol = closure_data_symbol;
lowlevel_enum_lambda_set_to_switch( lowlevel_enum_lambda_set_to_switch(
@ -9261,7 +9245,6 @@ where
hole, hole,
) )
} }
other => internal_error!("Unexpected multi-dispatch layout: {:?}", other),
}, },
} }
} }
@ -9446,8 +9429,8 @@ fn match_on_lambda_set<'a>(
hole, hole,
) )
} }
ClosureCallOptions::MultiDispatch(layout) => match layout { ClosureCallOptions::EnumDispatch(repr) => match repr {
Layout::Builtin(Builtin::Bool) => { EnumDispatch::Bool => {
let closure_tag_id_symbol = closure_data_symbol; let closure_tag_id_symbol = closure_data_symbol;
enum_lambda_set_to_switch( enum_lambda_set_to_switch(
@ -9462,7 +9445,7 @@ fn match_on_lambda_set<'a>(
hole, hole,
) )
} }
Layout::Builtin(Builtin::Int(IntWidth::U8)) => { EnumDispatch::U8 => {
let closure_tag_id_symbol = closure_data_symbol; let closure_tag_id_symbol = closure_data_symbol;
enum_lambda_set_to_switch( enum_lambda_set_to_switch(
@ -9477,7 +9460,6 @@ fn match_on_lambda_set<'a>(
hole, hole,
) )
} }
other => internal_error!("Unexpected multi-dispatch layout: {:?}", other),
}, },
} }
} }

View file

@ -788,6 +788,12 @@ pub struct LambdaSet<'a> {
representation: &'a Layout<'a>, representation: &'a Layout<'a>,
} }
#[derive(Debug)]
pub enum EnumDispatch {
Bool,
U8,
}
/// representation of the closure *for a particular function* /// representation of the closure *for a particular function*
#[derive(Debug)] #[derive(Debug)]
pub enum ClosureRepresentation<'a> { pub enum ClosureRepresentation<'a> {
@ -804,11 +810,11 @@ pub enum ClosureRepresentation<'a> {
/// ///
/// We MUST sort these according to their stack size before code gen! /// We MUST sort these according to their stack size before code gen!
AlphabeticOrderStruct(&'a [Layout<'a>]), AlphabeticOrderStruct(&'a [Layout<'a>]),
/// The closure dispatches to multiple functions, but none of them capture anything, so this is
/// a boolean or integer flag.
MultiDispatch(Layout<'a>),
/// The closure is one function that captures a single identifier, whose value is unwrapped. /// The closure is one function that captures a single identifier, whose value is unwrapped.
UnwrappedCapture(Layout<'a>), UnwrappedCapture(Layout<'a>),
/// The closure dispatches to multiple functions, but none of them capture anything, so this is
/// a boolean or integer flag.
EnumDispatch(EnumDispatch),
} }
/// How the closure should be seen when determining a call-by-name. /// How the closure should be seen when determining a call-by-name.
@ -823,10 +829,10 @@ pub enum ClosureCallOptions<'a> {
field_layouts: &'a [Layout<'a>], field_layouts: &'a [Layout<'a>],
field_order_hash: FieldOrderHash, field_order_hash: FieldOrderHash,
}, },
/// The closure dispatches to multiple possible functions, none of which capture.
MultiDispatch(Layout<'a>),
/// The closure is one function that captures a single identifier, whose value is unwrapped. /// The closure is one function that captures a single identifier, whose value is unwrapped.
UnwrappedCapture(Layout<'a>), UnwrappedCapture(Layout<'a>),
/// The closure dispatches to multiple possible functions, none of which capture.
EnumDispatch(EnumDispatch),
} }
impl<'a> LambdaSet<'a> { impl<'a> LambdaSet<'a> {
@ -842,7 +848,7 @@ impl<'a> LambdaSet<'a> {
pub fn is_represented(&self) -> Option<Layout<'a>> { pub fn is_represented(&self) -> Option<Layout<'a>> {
if self.has_unwrapped_capture_repr() { if self.has_unwrapped_capture_repr() {
Some(*self.representation) Some(*self.representation)
} else if self.has_multi_dispatch_repr() { } else if self.has_enum_dispatch_repr() {
None None
} else { } else {
match self.representation { match self.representation {
@ -1036,11 +1042,13 @@ impl<'a> LambdaSet<'a> {
ClosureRepresentation::AlphabeticOrderStruct(fields) ClosureRepresentation::AlphabeticOrderStruct(fields)
} }
layout => { layout => {
debug_assert!( debug_assert!(self.has_enum_dispatch_repr(),);
self.has_multi_dispatch_repr(), let enum_repr = match layout {
"Expected this to be a multi-dispatching closure, but it was something else!" Layout::Builtin(Builtin::Bool) => EnumDispatch::Bool,
); Layout::Builtin(Builtin::Int(IntWidth::U8)) => EnumDispatch::U8,
ClosureRepresentation::MultiDispatch(*layout) other => internal_error!("Invalid layout for enum dispatch: {:?}", other),
};
ClosureRepresentation::EnumDispatch(enum_repr)
} }
} }
} }
@ -1049,7 +1057,7 @@ impl<'a> LambdaSet<'a> {
self.set.len() == 1 && self.set[0].1.len() == 1 self.set.len() == 1 && self.set[0].1.len() == 1
} }
fn has_multi_dispatch_repr(&self) -> bool { fn has_enum_dispatch_repr(&self) -> bool {
self.set.len() > 1 && self.set.iter().all(|(_, captures)| captures.is_empty()) self.set.len() > 1 && self.set.iter().all(|(_, captures)| captures.is_empty())
} }
@ -1077,8 +1085,13 @@ impl<'a> LambdaSet<'a> {
} }
} }
layout => { layout => {
debug_assert!(self.has_multi_dispatch_repr()); debug_assert!(self.has_enum_dispatch_repr());
ClosureCallOptions::MultiDispatch(*layout) let enum_repr = match layout {
Layout::Builtin(Builtin::Bool) => EnumDispatch::Bool,
Layout::Builtin(Builtin::Int(IntWidth::U8)) => EnumDispatch::U8,
other => internal_error!("Invalid layout for enum dispatch: {:?}", other),
};
ClosureCallOptions::EnumDispatch(enum_repr)
} }
} }
} }
@ -1106,7 +1119,7 @@ impl<'a> LambdaSet<'a> {
arguments.into_bump_slice() arguments.into_bump_slice()
} }
ClosureCallOptions::MultiDispatch(_) => { ClosureCallOptions::EnumDispatch(_) => {
// No captures, don't pass this along // No captures, don't pass this along
argument_layouts argument_layouts
} }