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)]
use crate::layout::{
Builtin, CapturesNiche, ClosureCallOptions, ClosureRepresentation, LambdaName, LambdaSet,
Layout, LayoutCache, LayoutProblem, RawFunctionLayout, TagIdIntType, UnionLayout,
Builtin, CapturesNiche, ClosureCallOptions, ClosureRepresentation, EnumDispatch, LambdaName,
LambdaSet, Layout, LayoutCache, LayoutProblem, RawFunctionLayout, TagIdIntType, UnionLayout,
WrappedVariant,
};
use bumpalo::collections::{CollectIn, Vec};
@ -3269,23 +3269,10 @@ fn specialize_external<'a>(
);
}
ClosureRepresentation::MultiDispatch(layout) => match layout {
Layout::Builtin(Builtin::Bool) => {
ClosureRepresentation::EnumDispatch(_) => {
// just ignore this value, since it's not a capture
// 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([])) => {}
@ -5448,8 +5435,8 @@ where
hole,
)
}
ClosureRepresentation::MultiDispatch(layout) => match layout {
Layout::Builtin(Builtin::Bool) => {
ClosureRepresentation::EnumDispatch(repr) => match repr {
EnumDispatch::Bool => {
debug_assert_eq!(symbols.len(), 0);
debug_assert_eq!(lambda_set.set.len(), 2);
@ -5458,7 +5445,7 @@ where
Stmt::Let(assigned, expr, lambda_set_layout, hole)
}
Layout::Builtin(Builtin::Int(IntWidth::U8)) => {
EnumDispatch::U8 => {
debug_assert_eq!(symbols.len(), 0);
debug_assert!(lambda_set.set.len() > 2);
@ -5471,9 +5458,6 @@ where
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))
}
ClosureCallOptions::MultiDispatch(layout) => match layout {
Layout::Builtin(Builtin::Bool) => {
ClosureCallOptions::EnumDispatch(repr) => match repr {
EnumDispatch::Bool => {
let closure_tag_id_symbol = closure_data_symbol;
lowlevel_enum_lambda_set_to_switch(
@ -9245,7 +9229,7 @@ where
hole,
)
}
Layout::Builtin(Builtin::Int(IntWidth::U8)) => {
EnumDispatch::U8 => {
let closure_tag_id_symbol = closure_data_symbol;
lowlevel_enum_lambda_set_to_switch(
@ -9261,7 +9245,6 @@ where
hole,
)
}
other => internal_error!("Unexpected multi-dispatch layout: {:?}", other),
},
}
}
@ -9446,8 +9429,8 @@ fn match_on_lambda_set<'a>(
hole,
)
}
ClosureCallOptions::MultiDispatch(layout) => match layout {
Layout::Builtin(Builtin::Bool) => {
ClosureCallOptions::EnumDispatch(repr) => match repr {
EnumDispatch::Bool => {
let closure_tag_id_symbol = closure_data_symbol;
enum_lambda_set_to_switch(
@ -9462,7 +9445,7 @@ fn match_on_lambda_set<'a>(
hole,
)
}
Layout::Builtin(Builtin::Int(IntWidth::U8)) => {
EnumDispatch::U8 => {
let closure_tag_id_symbol = closure_data_symbol;
enum_lambda_set_to_switch(
@ -9477,7 +9460,6 @@ fn match_on_lambda_set<'a>(
hole,
)
}
other => internal_error!("Unexpected multi-dispatch layout: {:?}", other),
},
}
}

View file

@ -788,6 +788,12 @@ pub struct LambdaSet<'a> {
representation: &'a Layout<'a>,
}
#[derive(Debug)]
pub enum EnumDispatch {
Bool,
U8,
}
/// representation of the closure *for a particular function*
#[derive(Debug)]
pub enum ClosureRepresentation<'a> {
@ -804,11 +810,11 @@ pub enum ClosureRepresentation<'a> {
///
/// We MUST sort these according to their stack size before code gen!
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.
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.
@ -823,10 +829,10 @@ pub enum ClosureCallOptions<'a> {
field_layouts: &'a [Layout<'a>],
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.
UnwrappedCapture(Layout<'a>),
/// The closure dispatches to multiple possible functions, none of which capture.
EnumDispatch(EnumDispatch),
}
impl<'a> LambdaSet<'a> {
@ -842,7 +848,7 @@ impl<'a> LambdaSet<'a> {
pub fn is_represented(&self) -> Option<Layout<'a>> {
if self.has_unwrapped_capture_repr() {
Some(*self.representation)
} else if self.has_multi_dispatch_repr() {
} else if self.has_enum_dispatch_repr() {
None
} else {
match self.representation {
@ -1036,11 +1042,13 @@ impl<'a> LambdaSet<'a> {
ClosureRepresentation::AlphabeticOrderStruct(fields)
}
layout => {
debug_assert!(
self.has_multi_dispatch_repr(),
"Expected this to be a multi-dispatching closure, but it was something else!"
);
ClosureRepresentation::MultiDispatch(*layout)
debug_assert!(self.has_enum_dispatch_repr(),);
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),
};
ClosureRepresentation::EnumDispatch(enum_repr)
}
}
}
@ -1049,7 +1057,7 @@ impl<'a> LambdaSet<'a> {
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())
}
@ -1077,8 +1085,13 @@ impl<'a> LambdaSet<'a> {
}
}
layout => {
debug_assert!(self.has_multi_dispatch_repr());
ClosureCallOptions::MultiDispatch(*layout)
debug_assert!(self.has_enum_dispatch_repr());
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()
}
ClosureCallOptions::MultiDispatch(_) => {
ClosureCallOptions::EnumDispatch(_) => {
// No captures, don't pass this along
argument_layouts
}