mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-27 22:09:09 +00:00
commit
519b4f2a12
10 changed files with 99 additions and 203 deletions
|
@ -40,24 +40,19 @@ pub enum Layout<'a> {
|
|||
/// A layout that is empty (turns into the empty struct in LLVM IR
|
||||
/// but for our purposes, not zero-sized, so it does not get dropped from data structures
|
||||
/// this is important for closures that capture zero-sized values
|
||||
PhantomEmptyStruct,
|
||||
Struct(&'a [Layout<'a>]),
|
||||
Union(UnionLayout<'a>),
|
||||
RecursivePointer,
|
||||
/// A function. The types of its arguments, then the type of its return value.
|
||||
FunctionPointer(&'a [Layout<'a>], &'a Layout<'a>),
|
||||
Closure(&'a [Layout<'a>], LambdaSet<'a>, &'a Layout<'a>),
|
||||
Pointer(&'a Layout<'a>),
|
||||
}
|
||||
|
||||
impl<'a> Layout<'a> {
|
||||
pub fn in_place(&self) -> InPlace {
|
||||
match self {
|
||||
Layout::Builtin(Builtin::EmptyList) => InPlace::InPlace,
|
||||
Layout::Builtin(Builtin::List(memory_mode, _)) => match memory_mode {
|
||||
MemoryMode::Unique => InPlace::InPlace,
|
||||
MemoryMode::Refcounted => InPlace::Clone,
|
||||
},
|
||||
Layout::Builtin(Builtin::List(_)) => InPlace::Clone,
|
||||
Layout::Builtin(Builtin::EmptyStr) => InPlace::InPlace,
|
||||
Layout::Builtin(Builtin::Str) => InPlace::Clone,
|
||||
Layout::Builtin(Builtin::Int1) => InPlace::Clone,
|
||||
|
@ -337,12 +332,6 @@ impl<'a> LambdaSet<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Copy)]
|
||||
pub enum MemoryMode {
|
||||
Unique,
|
||||
Refcounted,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Builtin<'a> {
|
||||
Int128,
|
||||
|
@ -359,7 +348,7 @@ pub enum Builtin<'a> {
|
|||
Str,
|
||||
Dict(&'a Layout<'a>, &'a Layout<'a>),
|
||||
Set(&'a Layout<'a>),
|
||||
List(MemoryMode, &'a Layout<'a>),
|
||||
List(&'a Layout<'a>),
|
||||
EmptyStr,
|
||||
EmptyList,
|
||||
EmptyDict,
|
||||
|
@ -483,7 +472,6 @@ impl<'a> Layout<'a> {
|
|||
|
||||
match self {
|
||||
Builtin(builtin) => builtin.safe_to_memcpy(),
|
||||
PhantomEmptyStruct => true,
|
||||
Struct(fields) => fields
|
||||
.iter()
|
||||
.all(|field_layout| field_layout.safe_to_memcpy()),
|
||||
|
@ -508,10 +496,6 @@ impl<'a> Layout<'a> {
|
|||
true
|
||||
}
|
||||
Closure(_, closure_layout, _) => closure_layout.safe_to_memcpy(),
|
||||
Pointer(_) => {
|
||||
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
|
||||
false
|
||||
}
|
||||
RecursivePointer => {
|
||||
// We cannot memcpy pointers, because then we would have the same pointer in multiple places!
|
||||
false
|
||||
|
@ -523,12 +507,7 @@ impl<'a> Layout<'a> {
|
|||
// For this calculation, we don't need an accurate
|
||||
// stack size, we just need to know whether it's zero,
|
||||
// so it's fine to use a pointer size of 1.
|
||||
if let Layout::PhantomEmptyStruct = self {
|
||||
false
|
||||
} else {
|
||||
// self.stack_size(1) == 0
|
||||
false
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn stack_size(&self, pointer_size: u32) -> u32 {
|
||||
|
@ -536,7 +515,6 @@ impl<'a> Layout<'a> {
|
|||
|
||||
match self {
|
||||
Builtin(builtin) => builtin.stack_size(pointer_size),
|
||||
PhantomEmptyStruct => 0,
|
||||
Struct(fields) => {
|
||||
let mut sum = 0;
|
||||
|
||||
|
@ -570,7 +548,6 @@ impl<'a> Layout<'a> {
|
|||
Closure(_, lambda_set, _) => lambda_set.stack_size(pointer_size),
|
||||
FunctionPointer(_, _) => pointer_size,
|
||||
RecursivePointer => pointer_size,
|
||||
Pointer(_) => pointer_size,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -600,10 +577,8 @@ impl<'a> Layout<'a> {
|
|||
}
|
||||
}
|
||||
Layout::Builtin(builtin) => builtin.alignment_bytes(pointer_size),
|
||||
Layout::PhantomEmptyStruct => 0,
|
||||
Layout::RecursivePointer => pointer_size,
|
||||
Layout::FunctionPointer(_, _) => pointer_size,
|
||||
Layout::Pointer(_) => pointer_size,
|
||||
Layout::Closure(_, captured, _) => {
|
||||
pointer_size.max(captured.alignment_bytes(pointer_size))
|
||||
}
|
||||
|
@ -626,7 +601,7 @@ impl<'a> Layout<'a> {
|
|||
|
||||
RecursivePointer => true,
|
||||
|
||||
Builtin(List(MemoryMode::Refcounted, _)) | Builtin(Str) => true,
|
||||
Builtin(List(_)) | Builtin(Str) => true,
|
||||
|
||||
_ => false,
|
||||
}
|
||||
|
@ -640,7 +615,6 @@ impl<'a> Layout<'a> {
|
|||
|
||||
match self {
|
||||
Builtin(builtin) => builtin.is_refcounted(),
|
||||
PhantomEmptyStruct => false,
|
||||
Struct(fields) => fields.iter().any(|f| f.contains_refcounted()),
|
||||
Union(variant) => {
|
||||
use UnionLayout::*;
|
||||
|
@ -659,7 +633,7 @@ impl<'a> Layout<'a> {
|
|||
}
|
||||
RecursivePointer => true,
|
||||
Closure(_, closure_layout, _) => closure_layout.contains_refcounted(),
|
||||
FunctionPointer(_, _) | Pointer(_) => false,
|
||||
FunctionPointer(_, _) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -673,7 +647,6 @@ impl<'a> Layout<'a> {
|
|||
|
||||
match self {
|
||||
Builtin(builtin) => builtin.to_doc(alloc, parens),
|
||||
PhantomEmptyStruct => alloc.text("{}"),
|
||||
Struct(fields) => {
|
||||
let fields_doc = fields.iter().map(|x| x.to_doc(alloc, parens));
|
||||
|
||||
|
@ -706,7 +679,6 @@ impl<'a> Layout<'a> {
|
|||
.append(" |} -> ")
|
||||
.append(result.to_doc(alloc, Parens::InFunction))
|
||||
}
|
||||
Pointer(_) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -878,7 +850,7 @@ impl<'a> Builtin<'a> {
|
|||
Str | EmptyStr => Builtin::STR_WORDS * pointer_size,
|
||||
Dict(_, _) | EmptyDict => Builtin::DICT_WORDS * pointer_size,
|
||||
Set(_) | EmptySet => Builtin::SET_WORDS * pointer_size,
|
||||
List(_, _) | EmptyList => Builtin::LIST_WORDS * pointer_size,
|
||||
List(_) | EmptyList => Builtin::LIST_WORDS * pointer_size,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -904,7 +876,7 @@ impl<'a> Builtin<'a> {
|
|||
Str | EmptyStr => pointer_size,
|
||||
Dict(_, _) | EmptyDict => pointer_size,
|
||||
Set(_) | EmptySet => pointer_size,
|
||||
List(_, _) | EmptyList => pointer_size,
|
||||
List(_) | EmptyList => pointer_size,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -914,7 +886,7 @@ impl<'a> Builtin<'a> {
|
|||
match self {
|
||||
Int128 | Int64 | Int32 | Int16 | Int8 | Int1 | Usize | Float128 | Float64 | Float32
|
||||
| Float16 | EmptyStr | EmptyDict | EmptyList | EmptySet => true,
|
||||
Str | Dict(_, _) | Set(_) | List(_, _) => false,
|
||||
Str | Dict(_, _) | Set(_) | List(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -925,10 +897,7 @@ impl<'a> Builtin<'a> {
|
|||
match self {
|
||||
Int128 | Int64 | Int32 | Int16 | Int8 | Int1 | Usize | Float128 | Float64 | Float32
|
||||
| Float16 | EmptyStr | EmptyDict | EmptyList | EmptySet => false,
|
||||
List(mode, element_layout) => match mode {
|
||||
MemoryMode::Refcounted => true,
|
||||
MemoryMode::Unique => element_layout.contains_refcounted(),
|
||||
},
|
||||
List(_) => true,
|
||||
|
||||
Str | Dict(_, _) | Set(_) => true,
|
||||
}
|
||||
|
@ -961,7 +930,7 @@ impl<'a> Builtin<'a> {
|
|||
EmptySet => alloc.text("EmptySet"),
|
||||
|
||||
Str => alloc.text("Str"),
|
||||
List(_, layout) => alloc
|
||||
List(layout) => alloc
|
||||
.text("List ")
|
||||
.append(layout.to_doc(alloc, Parens::InTypeParam)),
|
||||
Set(layout) => alloc
|
||||
|
@ -1901,11 +1870,7 @@ pub fn list_layout_from_elem<'a>(
|
|||
_ => {
|
||||
let elem_layout = Layout::from_var(env, elem_var)?;
|
||||
|
||||
// This is a normal list.
|
||||
Ok(Layout::Builtin(Builtin::List(
|
||||
MemoryMode::Refcounted,
|
||||
env.arena.alloc(elem_layout),
|
||||
)))
|
||||
Ok(Layout::Builtin(Builtin::List(env.arena.alloc(elem_layout))))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1971,7 +1936,7 @@ impl<'a> std::convert::TryFrom<&Layout<'a>> for ListLayout<'a> {
|
|||
fn try_from(value: &Layout<'a>) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
Layout::Builtin(Builtin::EmptyList) => Ok(ListLayout::EmptyList),
|
||||
Layout::Builtin(Builtin::List(_, element)) => Ok(ListLayout::List(element)),
|
||||
Layout::Builtin(Builtin::List(element)) => Ok(ListLayout::List(element)),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue