mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 11:52:19 +00:00
Merge pull request #4847 from roc-lang/intern-layouts-3
Wrap layout interners in own trait
This commit is contained in:
commit
4ff7c13ab3
15 changed files with 237 additions and 109 deletions
|
@ -7,8 +7,7 @@ The user needs to analyse the Wasm module's memory to decode the result.
|
|||
use bumpalo::{collections::Vec, Bump};
|
||||
|
||||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
use roc_intern::Interner;
|
||||
use roc_mono::layout::{Builtin, Layout, UnionLayout};
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutInterner, UnionLayout};
|
||||
use roc_std::{RocDec, RocList, RocOrder, RocResult, RocStr, I128, U128};
|
||||
use roc_target::TargetInfo;
|
||||
use roc_wasm_module::{
|
||||
|
@ -39,7 +38,7 @@ pub trait Wasm32Result {
|
|||
/// Layout-driven wrapper generation
|
||||
pub fn insert_wrapper_for_layout<'a>(
|
||||
arena: &'a Bump,
|
||||
interner: &impl Interner<'a, Layout<'a>>,
|
||||
interner: &impl LayoutInterner<'a>,
|
||||
module: &mut WasmModule<'a>,
|
||||
wrapper_name: &'static str,
|
||||
main_fn_index: u32,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
use std::{
|
||||
cell::RefCell,
|
||||
hash::{BuildHasher, Hash, Hasher},
|
||||
marker::PhantomData,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
|
@ -23,6 +24,25 @@ impl<T> Clone for Interned<T> {
|
|||
|
||||
impl<T> Copy for Interned<T> {}
|
||||
|
||||
impl<T> Interned<T> {
|
||||
/// # Safety
|
||||
///
|
||||
/// The index is not guaranteed to exist. Use this only when creating an interner with constant
|
||||
/// indices, with the variant that `insert` returns a monotonically increasing index.
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```ignore(illustrative)
|
||||
/// let reserved_interned = Interned::from_reserved_index(0);
|
||||
/// let interner = GlobalInterner::with_capacity(1);
|
||||
/// let inserted = interner.insert("something");
|
||||
/// assert_eq!(reserved_interned, inserted);
|
||||
/// ```
|
||||
pub const unsafe fn from_reserved_index(index: usize) -> Self {
|
||||
Self(index, PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
/// A concurrent interner, suitable for usage between threads.
|
||||
///
|
||||
/// The interner does not currently maintain its own arena; you will have to supply
|
||||
|
@ -143,6 +163,10 @@ impl<'a, K: Hash + Eq> GlobalInterner<'a, K> {
|
|||
let Interned(index, _) = interned;
|
||||
self.vec.read()[index]
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.vec.read().is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: Hash + Eq> ThreadLocalInterner<'a, K> {
|
||||
|
@ -201,6 +225,10 @@ impl<'a, K> SingleThreadedInterner<'a, K> {
|
|||
vec: RwLock::new(vec),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.vec.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: Hash + Eq> Interner<'a, K> for SingleThreadedInterner<'a, K> {
|
||||
|
|
|
@ -24,7 +24,6 @@ use roc_debug_flags::{
|
|||
};
|
||||
use roc_derive::SharedDerivedModule;
|
||||
use roc_error_macros::internal_error;
|
||||
use roc_intern::{GlobalInterner, SingleThreadedInterner};
|
||||
use roc_late_solve::{AbilitiesView, WorldAbilities};
|
||||
use roc_module::ident::{Ident, ModuleName, QualifiedModuleName};
|
||||
use roc_module::symbol::{
|
||||
|
@ -35,7 +34,9 @@ use roc_mono::ir::{
|
|||
CapturedSymbols, ExternalSpecializations, PartialProc, Proc, ProcLayout, Procs, ProcsBase,
|
||||
UpdateModeIds,
|
||||
};
|
||||
use roc_mono::layout::{LambdaName, Layout, LayoutCache, LayoutProblem, Niche, STLayoutInterner};
|
||||
use roc_mono::layout::{
|
||||
GlobalLayoutInterner, LambdaName, Layout, LayoutCache, LayoutProblem, Niche, STLayoutInterner,
|
||||
};
|
||||
use roc_packaging::cache::{self, RocCacheDir};
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
use roc_packaging::https::PackageMetadata;
|
||||
|
@ -749,7 +750,7 @@ pub struct MonomorphizedModule<'a> {
|
|||
pub module_id: ModuleId,
|
||||
pub interns: Interns,
|
||||
pub subs: Subs,
|
||||
pub layout_interner: SingleThreadedInterner<'a, Layout<'a>>,
|
||||
pub layout_interner: STLayoutInterner<'a>,
|
||||
pub output_path: Box<Path>,
|
||||
pub can_problems: MutMap<ModuleId, Vec<roc_problem::can::Problem>>,
|
||||
pub type_problems: MutMap<ModuleId, Vec<TypeError>>,
|
||||
|
@ -766,7 +767,7 @@ pub struct MonomorphizedModule<'a> {
|
|||
/// Values used to render expect output
|
||||
pub struct ExpectMetadata<'a> {
|
||||
pub interns: Interns,
|
||||
pub layout_interner: SingleThreadedInterner<'a, Layout<'a>>,
|
||||
pub layout_interner: STLayoutInterner<'a>,
|
||||
pub expectations: VecMap<ModuleId, Expectations>,
|
||||
}
|
||||
|
||||
|
@ -1013,7 +1014,7 @@ struct State<'a> {
|
|||
// cached types (used for builtin modules, could include packages in the future too)
|
||||
cached_types: CachedTypeState,
|
||||
|
||||
layout_interner: Arc<GlobalInterner<'a, Layout<'a>>>,
|
||||
layout_interner: GlobalLayoutInterner<'a>,
|
||||
}
|
||||
|
||||
type CachedTypeState = Arc<Mutex<MutMap<ModuleId, TypeState>>>;
|
||||
|
@ -1071,7 +1072,7 @@ impl<'a> State<'a> {
|
|||
exec_mode,
|
||||
make_specializations_pass: MakeSpecializationsPass::Pass(1),
|
||||
world_abilities: Default::default(),
|
||||
layout_interner: GlobalInterner::with_capacity(128),
|
||||
layout_interner: GlobalLayoutInterner::with_capacity(128),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3071,7 +3072,7 @@ fn update<'a>(
|
|||
}
|
||||
|
||||
let layout_interner = {
|
||||
let mut taken = GlobalInterner::with_capacity(0);
|
||||
let mut taken = GlobalLayoutInterner::with_capacity(0);
|
||||
std::mem::swap(&mut state.layout_interner, &mut taken);
|
||||
taken
|
||||
};
|
||||
|
|
|
@ -11,7 +11,9 @@ use crate::code_gen_help::let_lowlevel;
|
|||
use crate::ir::{
|
||||
BranchInfo, Call, CallType, Expr, JoinPointId, Literal, ModifyRc, Param, Stmt, UpdateModeId,
|
||||
};
|
||||
use crate::layout::{Builtin, InLayout, Layout, STLayoutInterner, TagIdIntType, UnionLayout};
|
||||
use crate::layout::{
|
||||
Builtin, InLayout, Layout, LayoutInterner, STLayoutInterner, TagIdIntType, UnionLayout,
|
||||
};
|
||||
|
||||
use super::{CodeGenHelp, Context, HelperOp};
|
||||
|
||||
|
@ -420,7 +422,7 @@ pub fn refcount_reset_proc_body<'a>(
|
|||
// progress incrementally. Kept in sync with generate_procs using assertions.
|
||||
pub fn is_rc_implemented_yet<'a, I>(interner: &I, layout: &Layout<'a>) -> bool
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
use UnionLayout::*;
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use roc_intern::Interner;
|
||||
use roc_module::symbol::{Interns, Symbol};
|
||||
use ven_pretty::{Arena, DocAllocator, DocBuilder};
|
||||
|
||||
use crate::{
|
||||
ir::{Parens, ProcLayout},
|
||||
layout::Layout,
|
||||
layout::{Layout, LayoutInterner},
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
@ -20,7 +19,7 @@ pub fn format_problems<'a, I>(
|
|||
problems: Problems<'a>,
|
||||
) -> impl Display
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let Problems(problems) = problems;
|
||||
let f = Arena::new();
|
||||
|
@ -44,7 +43,7 @@ fn format_problem<'a, 'd, I>(
|
|||
) -> Doc<'d>
|
||||
where
|
||||
'a: 'd,
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let Problem {
|
||||
proc,
|
||||
|
@ -118,7 +117,7 @@ fn format_kind<'a, 'd, I>(
|
|||
kind: ProblemKind<'a>,
|
||||
) -> (&'static str, Vec<(usize, Doc<'d>)>, Doc<'d>)
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let title;
|
||||
let docs_before;
|
||||
|
@ -445,7 +444,7 @@ fn format_proc_spec<'a, 'd, I>(
|
|||
proc_layout: ProcLayout<'a>,
|
||||
) -> Doc<'d>
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
f.concat([
|
||||
f.as_string(symbol.as_str(interns)),
|
||||
|
@ -460,7 +459,7 @@ fn format_proc_layout<'a, 'd, I>(
|
|||
proc_layout: ProcLayout<'a>,
|
||||
) -> Doc<'d>
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let ProcLayout {
|
||||
arguments,
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::ir::{
|
|||
build_list_index_probe, BranchInfo, Call, CallType, DestructType, Env, Expr, JoinPointId,
|
||||
ListIndex, Literal, Param, Pattern, Procs, Stmt,
|
||||
};
|
||||
use crate::layout::{Builtin, Layout, LayoutCache, LayoutInterner, TagIdIntType, UnionLayout};
|
||||
use crate::layout::{Builtin, Layout, LayoutCache, TLLayoutInterner, TagIdIntType, UnionLayout};
|
||||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
use roc_collections::all::{MutMap, MutSet};
|
||||
use roc_error_macros::internal_error;
|
||||
|
@ -1359,7 +1359,7 @@ enum PathInstruction {
|
|||
|
||||
fn path_to_expr_help<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
layout_interner: &LayoutInterner<'a>,
|
||||
layout_interner: &TLLayoutInterner<'a>,
|
||||
mut symbol: Symbol,
|
||||
path: &[PathInstruction],
|
||||
mut layout: Layout<'a>,
|
||||
|
@ -1462,7 +1462,7 @@ fn path_to_expr_help<'a>(
|
|||
|
||||
fn test_to_comparison<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
layout_interner: &LayoutInterner<'a>,
|
||||
layout_interner: &TLLayoutInterner<'a>,
|
||||
cond_symbol: Symbol,
|
||||
cond_layout: &Layout<'a>,
|
||||
path: &[PathInstruction],
|
||||
|
@ -1619,7 +1619,7 @@ type Tests<'a> = std::vec::Vec<(
|
|||
|
||||
fn stores_and_condition<'a>(
|
||||
env: &mut Env<'a, '_>,
|
||||
layout_interner: &LayoutInterner<'a>,
|
||||
layout_interner: &TLLayoutInterner<'a>,
|
||||
cond_symbol: Symbol,
|
||||
cond_layout: &Layout<'a>,
|
||||
test_chain: Vec<(Vec<PathInstruction>, Test<'a>)>,
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
use crate::layout::{
|
||||
self, Builtin, ClosureCallOptions, ClosureRepresentation, EnumDispatch, LambdaName, LambdaSet,
|
||||
Layout, LayoutCache, LayoutProblem, Niche, RawFunctionLayout, STLayoutInterner, TagIdIntType,
|
||||
UnionLayout, WrappedVariant,
|
||||
Layout, LayoutCache, LayoutInterner, LayoutProblem, Niche, RawFunctionLayout, STLayoutInterner,
|
||||
TagIdIntType, UnionLayout, WrappedVariant,
|
||||
};
|
||||
use bumpalo::collections::{CollectIn, Vec};
|
||||
use bumpalo::Bump;
|
||||
|
@ -22,7 +22,6 @@ use roc_debug_flags::{
|
|||
use roc_derive::SharedDerivedModule;
|
||||
use roc_error_macros::{internal_error, todo_abilities};
|
||||
use roc_exhaustive::{Ctor, CtorName, ListArity, RenderAs, TagId};
|
||||
use roc_intern::Interner;
|
||||
use roc_late_solve::storage::{ExternalModuleStorage, ExternalModuleStorageSnapshot};
|
||||
use roc_late_solve::{resolve_ability_specialization, AbilitiesView, Resolved, UnificationFailed};
|
||||
use roc_module::ident::{ForeignSymbol, Lowercase, TagName};
|
||||
|
@ -339,7 +338,7 @@ impl<'a> Proc<'a> {
|
|||
D: DocAllocator<'b, A>,
|
||||
D::Doc: Clone,
|
||||
A: Clone,
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let args_doc = self.args.iter().map(|(layout, symbol)| {
|
||||
let arg_doc = symbol_to_doc(alloc, *symbol, pretty);
|
||||
|
@ -382,7 +381,7 @@ impl<'a> Proc<'a> {
|
|||
|
||||
pub fn to_pretty<I>(&self, interner: &I, width: usize, pretty: bool) -> String
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let allocator = BoxAllocator;
|
||||
let mut w = std::vec::Vec::new();
|
||||
|
@ -2173,7 +2172,7 @@ impl<'a> Stmt<'a> {
|
|||
D: DocAllocator<'b, A>,
|
||||
D::Doc: Clone,
|
||||
A: Clone,
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
use Stmt::*;
|
||||
|
||||
|
@ -2329,7 +2328,7 @@ impl<'a> Stmt<'a> {
|
|||
|
||||
pub fn to_pretty<I>(&self, interner: &I, width: usize, pretty: bool) -> String
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let allocator = BoxAllocator;
|
||||
let mut w = std::vec::Vec::new();
|
||||
|
|
|
@ -5,7 +5,7 @@ use bumpalo::Bump;
|
|||
use roc_builtins::bitcode::{FloatWidth, IntWidth};
|
||||
use roc_collections::all::{default_hasher, FnvMap, MutMap};
|
||||
use roc_error_macros::{internal_error, todo_abilities};
|
||||
use roc_intern::{Interner, SingleThreadedInterner, ThreadLocalInterner};
|
||||
use roc_intern::Interner;
|
||||
use roc_module::ident::{Lowercase, TagName};
|
||||
use roc_module::symbol::{Interns, Symbol};
|
||||
use roc_problem::can::RuntimeError;
|
||||
|
@ -22,6 +22,9 @@ use std::collections::HashMap;
|
|||
use std::hash::{Hash, Hasher};
|
||||
use ven_pretty::{DocAllocator, DocBuilder};
|
||||
|
||||
mod intern;
|
||||
pub use intern::{GlobalLayoutInterner, LayoutInterner, STLayoutInterner, TLLayoutInterner};
|
||||
|
||||
// if your changes cause this number to go down, great!
|
||||
// please change it to the lower number.
|
||||
// if it went up, maybe check that the change is really required
|
||||
|
@ -97,9 +100,6 @@ macro_rules! inc_stat {
|
|||
};
|
||||
}
|
||||
|
||||
pub type LayoutInterner<'a> = ThreadLocalInterner<'a, Layout<'a>>;
|
||||
pub type STLayoutInterner<'a> = SingleThreadedInterner<'a, Layout<'a>>;
|
||||
|
||||
/// Layout cache to avoid recomputing [Layout] from a [Variable] multiple times.
|
||||
#[derive(Debug)]
|
||||
pub struct LayoutCache<'a> {
|
||||
|
@ -107,7 +107,7 @@ pub struct LayoutCache<'a> {
|
|||
cache: std::vec::Vec<CacheLayer<LayoutResult<'a>>>,
|
||||
raw_function_cache: std::vec::Vec<CacheLayer<RawFunctionLayoutResult<'a>>>,
|
||||
|
||||
pub interner: LayoutInterner<'a>,
|
||||
pub interner: TLLayoutInterner<'a>,
|
||||
|
||||
/// Statistics on the usage of the layout cache.
|
||||
#[cfg(debug_assertions)]
|
||||
|
@ -117,7 +117,7 @@ pub struct LayoutCache<'a> {
|
|||
}
|
||||
|
||||
impl<'a> LayoutCache<'a> {
|
||||
pub fn new(interner: LayoutInterner<'a>, target_info: TargetInfo) -> Self {
|
||||
pub fn new(interner: TLLayoutInterner<'a>, target_info: TargetInfo) -> Self {
|
||||
let mut cache = std::vec::Vec::with_capacity(4);
|
||||
cache.push(CacheLayer::default());
|
||||
let mut raw_cache = std::vec::Vec::with_capacity(4);
|
||||
|
@ -743,7 +743,7 @@ impl<'a> UnionLayout<'a> {
|
|||
D: DocAllocator<'b, A>,
|
||||
D::Doc: Clone,
|
||||
A: Clone,
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
use UnionLayout::*;
|
||||
|
||||
|
@ -982,7 +982,7 @@ impl<'a> UnionLayout<'a> {
|
|||
target_info: TargetInfo,
|
||||
) -> u32
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
tags.iter()
|
||||
.map(|field_layouts| {
|
||||
|
@ -994,7 +994,7 @@ impl<'a> UnionLayout<'a> {
|
|||
|
||||
pub fn allocation_alignment_bytes<I>(&self, interner: &I, target_info: TargetInfo) -> u32
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let allocation = match self {
|
||||
UnionLayout::NonRecursive(tags) => {
|
||||
|
@ -1019,7 +1019,7 @@ impl<'a> UnionLayout<'a> {
|
|||
/// Size of the data in memory, whether it's stack or heap (for non-null tag ids)
|
||||
pub fn data_size_and_alignment<I>(&self, interner: &I, target_info: TargetInfo) -> (u32, u32)
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let (data_width, data_align) =
|
||||
self.data_size_and_alignment_help_match(interner, target_info);
|
||||
|
@ -1052,7 +1052,7 @@ impl<'a> UnionLayout<'a> {
|
|||
/// Returns None if the tag_id is not stored as data in the layout.
|
||||
pub fn data_size_without_tag_id<I>(&self, interner: &I, target_info: TargetInfo) -> Option<u32>
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
if !self.stores_tag_id_as_data(target_info) {
|
||||
return None;
|
||||
|
@ -1070,7 +1070,7 @@ impl<'a> UnionLayout<'a> {
|
|||
target_info: TargetInfo,
|
||||
) -> (u32, u32)
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
match self {
|
||||
Self::NonRecursive(tags) => {
|
||||
|
@ -1093,7 +1093,7 @@ impl<'a> UnionLayout<'a> {
|
|||
|
||||
pub fn tag_id_offset<I>(&self, interner: &I, target_info: TargetInfo) -> Option<u32>
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
match self {
|
||||
UnionLayout::NonRecursive(tags)
|
||||
|
@ -1111,7 +1111,7 @@ impl<'a> UnionLayout<'a> {
|
|||
target_info: TargetInfo,
|
||||
) -> u32
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let (data_width, data_align) =
|
||||
Layout::stack_size_and_alignment_slices(interner, layouts, target_info);
|
||||
|
@ -1122,7 +1122,7 @@ impl<'a> UnionLayout<'a> {
|
|||
/// Very important to use this when doing a memcpy!
|
||||
fn stack_size_without_alignment<I>(&self, interner: &I, target_info: TargetInfo) -> u32
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
match self {
|
||||
UnionLayout::NonRecursive(_) => {
|
||||
|
@ -1281,7 +1281,7 @@ impl<'a> Niche<'a> {
|
|||
D: DocAllocator<'b, A>,
|
||||
D::Doc: Clone,
|
||||
A: Clone,
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
match self.0 {
|
||||
NichePriv::Captures(captures) => alloc.concat([
|
||||
|
@ -1394,7 +1394,7 @@ pub enum ClosureCallOptions<'a> {
|
|||
impl<'a> LambdaSet<'a> {
|
||||
pub fn runtime_representation<I>(&self, interner: &I) -> Layout<'a>
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
*interner.get(self.representation)
|
||||
}
|
||||
|
@ -1406,7 +1406,7 @@ impl<'a> LambdaSet<'a> {
|
|||
|
||||
pub fn is_represented<I>(&self, interner: &I) -> Option<Layout<'a>>
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
if self.has_unwrapped_capture_repr() {
|
||||
let repr = interner.get(self.representation);
|
||||
|
@ -1450,7 +1450,7 @@ impl<'a> LambdaSet<'a> {
|
|||
lambda_name: LambdaName,
|
||||
) -> ClosureRepresentation<'a>
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
debug_assert!(self.contains(lambda_name.name));
|
||||
|
||||
|
@ -1475,7 +1475,7 @@ impl<'a> LambdaSet<'a> {
|
|||
captures_layouts: &[Layout],
|
||||
) -> LambdaName<'a>
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
debug_assert!(
|
||||
self.contains(function_symbol),
|
||||
|
@ -1516,7 +1516,7 @@ impl<'a> LambdaSet<'a> {
|
|||
/// Resolves recursive pointers to the layout of the lambda set.
|
||||
fn capture_layouts_eq<I>(&self, interner: &I, left: &InLayout<'a>, right: &Layout) -> bool
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let left = interner.get(*left);
|
||||
if left == right {
|
||||
|
@ -1550,7 +1550,7 @@ impl<'a> LambdaSet<'a> {
|
|||
|
||||
fn layout_for_member<I, F>(&self, interner: &I, comparator: F) -> ClosureRepresentation<'a>
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
F: Fn(Symbol, &[InLayout]) -> bool,
|
||||
{
|
||||
if self.has_unwrapped_capture_repr() {
|
||||
|
@ -1663,7 +1663,7 @@ impl<'a> LambdaSet<'a> {
|
|||
|
||||
pub fn call_by_name_options<I>(&self, interner: &I) -> ClosureCallOptions<'a>
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let repr = interner.get(self.representation);
|
||||
|
||||
|
@ -1907,7 +1907,7 @@ impl<'a> LambdaSet<'a> {
|
|||
|
||||
pub fn stack_size<I>(&self, interner: &I, target_info: TargetInfo) -> u32
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
interner
|
||||
.get(self.representation)
|
||||
|
@ -1915,7 +1915,7 @@ impl<'a> LambdaSet<'a> {
|
|||
}
|
||||
pub fn contains_refcounted<I>(&self, interner: &I) -> bool
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
interner
|
||||
.get(self.representation)
|
||||
|
@ -1923,14 +1923,14 @@ impl<'a> LambdaSet<'a> {
|
|||
}
|
||||
pub fn safe_to_memcpy<I>(&self, interner: &I) -> bool
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
interner.get(self.representation).safe_to_memcpy(interner)
|
||||
}
|
||||
|
||||
pub fn alignment_bytes<I>(&self, interner: &I, target_info: TargetInfo) -> u32
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
interner
|
||||
.get(self.representation)
|
||||
|
@ -2399,7 +2399,7 @@ impl<'a> Layout<'a> {
|
|||
|
||||
pub fn safe_to_memcpy<I>(&self, interner: &I) -> bool
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
use Layout::*;
|
||||
|
||||
|
@ -2445,7 +2445,7 @@ impl<'a> Layout<'a> {
|
|||
|
||||
pub fn is_passed_by_reference<I>(&self, interner: &I, target_info: TargetInfo) -> bool
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
match self {
|
||||
Layout::Builtin(builtin) => {
|
||||
|
@ -2472,7 +2472,7 @@ impl<'a> Layout<'a> {
|
|||
|
||||
pub fn stack_size<I>(&self, interner: &I, target_info: TargetInfo) -> u32
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let width = self.stack_size_without_alignment(interner, target_info);
|
||||
let alignment = self.alignment_bytes(interner, target_info);
|
||||
|
@ -2482,7 +2482,7 @@ impl<'a> Layout<'a> {
|
|||
|
||||
pub fn stack_size_and_alignment<I>(&self, interner: &I, target_info: TargetInfo) -> (u32, u32)
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let width = self.stack_size_without_alignment(interner, target_info);
|
||||
let alignment = self.alignment_bytes(interner, target_info);
|
||||
|
@ -2494,7 +2494,7 @@ impl<'a> Layout<'a> {
|
|||
/// Very important to use this when doing a memcpy!
|
||||
pub fn stack_size_without_alignment<I>(&self, interner: &I, target_info: TargetInfo) -> u32
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
use Layout::*;
|
||||
|
||||
|
@ -2520,7 +2520,7 @@ impl<'a> Layout<'a> {
|
|||
|
||||
pub fn alignment_bytes<I>(&self, interner: &I, target_info: TargetInfo) -> u32
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
match self {
|
||||
Layout::Struct { field_layouts, .. } => field_layouts
|
||||
|
@ -2572,7 +2572,7 @@ impl<'a> Layout<'a> {
|
|||
|
||||
pub fn allocation_alignment_bytes<I>(&self, interner: &I, target_info: TargetInfo) -> u32
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let ptr_width = target_info.ptr_width() as u32;
|
||||
|
||||
|
@ -2598,7 +2598,7 @@ impl<'a> Layout<'a> {
|
|||
target_info: TargetInfo,
|
||||
) -> (u32, u32)
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let mut data_align = 1;
|
||||
let mut data_width = 0;
|
||||
|
@ -2642,7 +2642,7 @@ impl<'a> Layout<'a> {
|
|||
/// goes out of scope, the refcount on those values/fields must be decremented.
|
||||
pub fn contains_refcounted<I>(&self, interner: &I) -> bool
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
use Layout::*;
|
||||
|
||||
|
@ -2683,7 +2683,7 @@ impl<'a> Layout<'a> {
|
|||
D: DocAllocator<'b, A>,
|
||||
D::Doc: Clone,
|
||||
A: Clone,
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
use Layout::*;
|
||||
|
||||
|
@ -2725,7 +2725,7 @@ impl<'a> Layout<'a> {
|
|||
|
||||
pub fn runtime_representation<I>(&self, interner: &I) -> Self
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
match self {
|
||||
Layout::LambdaSet(lambda_set) => lambda_set.runtime_representation(interner),
|
||||
|
@ -2927,7 +2927,7 @@ impl<'a> Builtin<'a> {
|
|||
D: DocAllocator<'b, A>,
|
||||
D::Doc: Clone,
|
||||
A: Clone,
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
use Builtin::*;
|
||||
|
||||
|
@ -2973,7 +2973,7 @@ impl<'a> Builtin<'a> {
|
|||
|
||||
pub fn allocation_alignment_bytes<I>(&self, interner: &I, target_info: TargetInfo) -> u32
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let ptr_width = target_info.ptr_width() as u32;
|
||||
|
||||
|
@ -4377,7 +4377,7 @@ pub fn cmp_fields<'a, L: Ord, I>(
|
|||
target_info: TargetInfo,
|
||||
) -> Ordering
|
||||
where
|
||||
I: Interner<'a, Layout<'a>>,
|
||||
I: LayoutInterner<'a>,
|
||||
{
|
||||
let size1 = layout1.alignment_bytes(interner, target_info);
|
||||
let size2 = layout2.alignment_bytes(interner, target_info);
|
||||
|
@ -4391,7 +4391,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn width_and_alignment_union_empty_struct() {
|
||||
let mut interner = SingleThreadedInterner::with_capacity(4);
|
||||
let mut interner = STLayoutInterner::with_capacity(4);
|
||||
|
||||
let lambda_set = LambdaSet {
|
||||
set: &[(Symbol::LIST_MAP, &[])],
|
||||
|
@ -4411,7 +4411,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn memcpy_size_result_u32_unit() {
|
||||
let interner = SingleThreadedInterner::with_capacity(4);
|
||||
let interner = STLayoutInterner::with_capacity(4);
|
||||
|
||||
let ok_tag = &[Layout::Builtin(Builtin::Int(IntWidth::U32))];
|
||||
let err_tag = &[Layout::UNIT];
|
||||
|
@ -4428,7 +4428,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn void_stack_size() {
|
||||
let interner = SingleThreadedInterner::with_capacity(4);
|
||||
let interner = STLayoutInterner::with_capacity(4);
|
||||
let target_info = TargetInfo::default_x86_64();
|
||||
assert_eq!(Layout::VOID.stack_size(&interner, target_info), 0);
|
||||
}
|
||||
|
|
109
crates/compiler/mono/src/layout/intern.rs
Normal file
109
crates/compiler/mono/src/layout/intern.rs
Normal file
|
@ -0,0 +1,109 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use roc_builtins::bitcode::IntWidth;
|
||||
use roc_intern::{GlobalInterner, Interned, Interner, SingleThreadedInterner, ThreadLocalInterner};
|
||||
|
||||
use super::{Builtin, Layout};
|
||||
|
||||
macro_rules! cache_interned_layouts {
|
||||
($($i:literal, $name:ident, $layout:expr)*; $total_constants:literal) => {
|
||||
pub trait LayoutInterner<'a>: Interner<'a, Layout<'a>> {
|
||||
$(
|
||||
const $name: Interned<Layout<'a>> = unsafe { Interned::from_reserved_index($i) };
|
||||
)*
|
||||
}
|
||||
|
||||
fn fill_reserved_layouts<'a>(interner: &mut STLayoutInterner<'a>) {
|
||||
assert!(interner.0.is_empty());
|
||||
$(
|
||||
interner.0.insert(&$layout);
|
||||
)*
|
||||
}
|
||||
|
||||
const fn _are_constants_in_order_non_redundant() -> usize {
|
||||
let mut total_seen = 0;
|
||||
$(total_seen += ($i * 0) + 1;)*
|
||||
match 0usize {
|
||||
$($i => {})*
|
||||
_ => {}
|
||||
}
|
||||
total_seen
|
||||
}
|
||||
|
||||
const _ASSERT_NON_REDUNDANT_CONSTANTS: () =
|
||||
assert!(_are_constants_in_order_non_redundant() == $total_constants);
|
||||
}
|
||||
}
|
||||
|
||||
cache_interned_layouts! {
|
||||
0, VOID, Layout::VOID
|
||||
1, UNIT, Layout::UNIT
|
||||
2, BOOL, Layout::Builtin(Builtin::Bool)
|
||||
3, U8, Layout::Builtin(Builtin::Int(IntWidth::U8))
|
||||
4, U16, Layout::Builtin(Builtin::Int(IntWidth::U16))
|
||||
5, U32, Layout::Builtin(Builtin::Int(IntWidth::U32))
|
||||
6, U64, Layout::Builtin(Builtin::Int(IntWidth::U64))
|
||||
7, U128, Layout::Builtin(Builtin::Int(IntWidth::U128))
|
||||
8, I8, Layout::Builtin(Builtin::Int(IntWidth::I8))
|
||||
9, I16, Layout::Builtin(Builtin::Int(IntWidth::I16))
|
||||
10, I32, Layout::Builtin(Builtin::Int(IntWidth::I32))
|
||||
11, I64, Layout::Builtin(Builtin::Int(IntWidth::I64))
|
||||
12, I128, Layout::Builtin(Builtin::Int(IntWidth::I128))
|
||||
|
||||
; 13
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GlobalLayoutInterner<'a>(Arc<GlobalInterner<'a, Layout<'a>>>);
|
||||
#[derive(Debug)]
|
||||
pub struct TLLayoutInterner<'a>(ThreadLocalInterner<'a, Layout<'a>>);
|
||||
#[derive(Debug)]
|
||||
pub struct STLayoutInterner<'a>(SingleThreadedInterner<'a, Layout<'a>>);
|
||||
|
||||
impl<'a> GlobalLayoutInterner<'a> {
|
||||
pub fn with_capacity(capacity: usize) -> Self {
|
||||
STLayoutInterner::with_capacity(capacity).into_global()
|
||||
}
|
||||
pub fn fork(&self) -> TLLayoutInterner<'a> {
|
||||
TLLayoutInterner(self.0.fork())
|
||||
}
|
||||
pub fn unwrap(self) -> Result<STLayoutInterner<'a>, Self> {
|
||||
match self.0.unwrap() {
|
||||
Ok(st) => Ok(STLayoutInterner(st)),
|
||||
Err(global) => Err(Self(global)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> STLayoutInterner<'a> {
|
||||
pub fn with_capacity(capacity: usize) -> Self {
|
||||
let mut interner = Self(SingleThreadedInterner::with_capacity(capacity));
|
||||
fill_reserved_layouts(&mut interner);
|
||||
interner
|
||||
}
|
||||
pub fn into_global(self) -> GlobalLayoutInterner<'a> {
|
||||
GlobalLayoutInterner(self.0.into_global())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Interner<'a, Layout<'a>> for TLLayoutInterner<'a> {
|
||||
fn insert(&mut self, value: &'a Layout<'a>) -> Interned<Layout<'a>> {
|
||||
self.0.insert(value)
|
||||
}
|
||||
|
||||
fn get(&self, key: Interned<Layout<'a>>) -> &'a Layout<'a> {
|
||||
self.0.get(key)
|
||||
}
|
||||
}
|
||||
impl<'a> LayoutInterner<'a> for TLLayoutInterner<'a> {}
|
||||
|
||||
impl<'a> Interner<'a, Layout<'a>> for STLayoutInterner<'a> {
|
||||
fn insert(&mut self, value: &'a Layout<'a>) -> Interned<Layout<'a>> {
|
||||
self.0.insert(value)
|
||||
}
|
||||
|
||||
fn get(&self, key: Interned<Layout<'a>>) -> &'a Layout<'a> {
|
||||
self.0.get(key)
|
||||
}
|
||||
}
|
||||
impl<'a> LayoutInterner<'a> for STLayoutInterner<'a> {}
|
Loading…
Add table
Add a link
Reference in a new issue