mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
Merge remote-tracking branch 'origin/trunk' into layout-builtin-numbers-refactor
This commit is contained in:
commit
f96d60a13e
9 changed files with 108 additions and 46 deletions
|
@ -22,17 +22,7 @@ pub struct ConstrainedModule {
|
||||||
pub constraint: Constraint,
|
pub constraint: Constraint,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn constrain_module(
|
pub fn constrain_module(declarations: &[Declaration], home: ModuleId) -> Constraint {
|
||||||
aliases: &MutMap<Symbol, Alias>,
|
|
||||||
declarations: &[Declaration],
|
|
||||||
home: ModuleId,
|
|
||||||
) -> Constraint {
|
|
||||||
let mut send_aliases = SendMap::default();
|
|
||||||
|
|
||||||
for (symbol, alias) in aliases.iter() {
|
|
||||||
send_aliases.insert(*symbol, alias.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
constrain_decls(home, declarations)
|
constrain_decls(home, declarations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -277,6 +277,7 @@ impl<'a> WasmBackend<'a> {
|
||||||
location,
|
location,
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
alignment_bytes,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
let (from_ptr, from_offset) =
|
let (from_ptr, from_offset) =
|
||||||
location.local_and_offset(self.storage.stack_frame_pointer);
|
location.local_and_offset(self.storage.stack_frame_pointer);
|
||||||
|
@ -623,6 +624,21 @@ impl<'a> WasmBackend<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
StoredValue::StackMemory { location, .. } => match lit {
|
StoredValue::StackMemory { location, .. } => match lit {
|
||||||
|
Literal::Decimal(decimal) => {
|
||||||
|
let (local_id, offset) =
|
||||||
|
location.local_and_offset(self.storage.stack_frame_pointer);
|
||||||
|
|
||||||
|
let lower_bits = decimal.0 as i64;
|
||||||
|
let upper_bits = (decimal.0 >> 64) as i64;
|
||||||
|
|
||||||
|
self.code_builder.get_local(local_id);
|
||||||
|
self.code_builder.i64_const(lower_bits);
|
||||||
|
self.code_builder.i64_store(Align::Bytes8, offset);
|
||||||
|
|
||||||
|
self.code_builder.get_local(local_id);
|
||||||
|
self.code_builder.i64_const(upper_bits);
|
||||||
|
self.code_builder.i64_store(Align::Bytes8, offset + 8);
|
||||||
|
}
|
||||||
Literal::Str(string) => {
|
Literal::Str(string) => {
|
||||||
let (local_id, offset) =
|
let (local_id, offset) =
|
||||||
location.local_and_offset(self.storage.stack_frame_pointer);
|
location.local_and_offset(self.storage.stack_frame_pointer);
|
||||||
|
|
|
@ -3,6 +3,15 @@ use roc_mono::layout::{Layout, UnionLayout};
|
||||||
|
|
||||||
use crate::{wasm_module::ValueType, PTR_SIZE, PTR_TYPE};
|
use crate::{wasm_module::ValueType, PTR_SIZE, PTR_TYPE};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum StackMemoryFormat {
|
||||||
|
/// Record, Str, List, Dict, etc.
|
||||||
|
Aggregate,
|
||||||
|
Int128,
|
||||||
|
Float128,
|
||||||
|
Decimal,
|
||||||
|
}
|
||||||
|
|
||||||
// See README for background information on Wasm locals, memory and function calls
|
// See README for background information on Wasm locals, memory and function calls
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum WasmLayout {
|
pub enum WasmLayout {
|
||||||
|
@ -11,7 +20,11 @@ pub enum WasmLayout {
|
||||||
Primitive(ValueType, u32),
|
Primitive(ValueType, u32),
|
||||||
|
|
||||||
// Local pointer to stack memory
|
// Local pointer to stack memory
|
||||||
StackMemory { size: u32, alignment_bytes: u32 },
|
StackMemory {
|
||||||
|
size: u32,
|
||||||
|
alignment_bytes: u32,
|
||||||
|
format: StackMemoryFormat,
|
||||||
|
},
|
||||||
|
|
||||||
// Local pointer to heap memory
|
// Local pointer to heap memory
|
||||||
HeapMemory,
|
HeapMemory,
|
||||||
|
@ -36,6 +49,7 @@ impl WasmLayout {
|
||||||
I128 | U128 => Self::StackMemory {
|
I128 | U128 => Self::StackMemory {
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
alignment_bytes,
|
||||||
|
format: StackMemoryFormat::Int128,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,26 +65,26 @@ impl WasmLayout {
|
||||||
F128 => Self::StackMemory {
|
F128 => Self::StackMemory {
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
alignment_bytes,
|
||||||
|
format: StackMemoryFormat::Float128,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Layout::Builtin(Decimal) => Self::StackMemory {
|
||||||
|
size,
|
||||||
|
alignment_bytes,
|
||||||
|
format: StackMemoryFormat::Decimal,
|
||||||
|
},
|
||||||
|
|
||||||
Layout::Builtin(
|
Layout::Builtin(
|
||||||
Decimal
|
Str | Dict(_, _) | Set(_) | List(_) | EmptyStr | EmptyList | EmptyDict | EmptySet,
|
||||||
| Str
|
|
||||||
| Dict(_, _)
|
|
||||||
| Set(_)
|
|
||||||
| List(_)
|
|
||||||
| EmptyStr
|
|
||||||
| EmptyList
|
|
||||||
| EmptyDict
|
|
||||||
| EmptySet,
|
|
||||||
)
|
)
|
||||||
| Layout::Struct(_)
|
| Layout::Struct(_)
|
||||||
| Layout::LambdaSet(_)
|
| Layout::LambdaSet(_)
|
||||||
| Layout::Union(NonRecursive(_)) => Self::StackMemory {
|
| Layout::Union(NonRecursive(_)) => Self::StackMemory {
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
alignment_bytes,
|
||||||
|
format: StackMemoryFormat::Aggregate,
|
||||||
},
|
},
|
||||||
|
|
||||||
Layout::Union(
|
Layout::Union(
|
||||||
|
|
|
@ -4,7 +4,7 @@ use bumpalo::Bump;
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
|
|
||||||
use crate::layout::WasmLayout;
|
use crate::layout::{StackMemoryFormat, WasmLayout};
|
||||||
use crate::wasm_module::{Align, CodeBuilder, LocalId, ValueType, VmSymbolState};
|
use crate::wasm_module::{Align, CodeBuilder, LocalId, ValueType, VmSymbolState};
|
||||||
use crate::{copy_memory, round_up_to_alignment, CopyMemoryConfig, PTR_SIZE, PTR_TYPE};
|
use crate::{copy_memory, round_up_to_alignment, CopyMemoryConfig, PTR_SIZE, PTR_TYPE};
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ pub enum StoredValue {
|
||||||
location: StackMemoryLocation,
|
location: StackMemoryLocation,
|
||||||
size: u32,
|
size: u32,
|
||||||
alignment_bytes: u32,
|
alignment_bytes: u32,
|
||||||
|
format: StackMemoryFormat,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,6 +148,7 @@ impl<'a> Storage<'a> {
|
||||||
WasmLayout::StackMemory {
|
WasmLayout::StackMemory {
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
alignment_bytes,
|
||||||
|
format,
|
||||||
} => {
|
} => {
|
||||||
let location = match kind {
|
let location = match kind {
|
||||||
StoredValueKind::Parameter => {
|
StoredValueKind::Parameter => {
|
||||||
|
@ -175,6 +177,7 @@ impl<'a> Storage<'a> {
|
||||||
location,
|
location,
|
||||||
size: *size,
|
size: *size,
|
||||||
alignment_bytes: *alignment_bytes,
|
alignment_bytes: *alignment_bytes,
|
||||||
|
format: *format,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -239,13 +242,26 @@ impl<'a> Storage<'a> {
|
||||||
code_builder.set_top_symbol(sym);
|
code_builder.set_top_symbol(sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
StoredValue::StackMemory { location, .. } => {
|
StoredValue::StackMemory {
|
||||||
|
location, format, ..
|
||||||
|
} => {
|
||||||
let (local_id, offset) = location.local_and_offset(self.stack_frame_pointer);
|
let (local_id, offset) = location.local_and_offset(self.stack_frame_pointer);
|
||||||
|
|
||||||
|
// Load the address of the value
|
||||||
code_builder.get_local(local_id);
|
code_builder.get_local(local_id);
|
||||||
if offset != 0 {
|
if offset != 0 {
|
||||||
code_builder.i32_const(offset as i32);
|
code_builder.i32_const(offset as i32);
|
||||||
code_builder.i32_add();
|
code_builder.i32_add();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if format != StackMemoryFormat::Aggregate {
|
||||||
|
// It's one of the 128-bit numbers, all of which we load as two i64's
|
||||||
|
// Mark the same Symbol twice in the VM value stack! Shouldn't matter except debug.
|
||||||
|
code_builder.i64_load(Align::Bytes8, offset);
|
||||||
|
code_builder.set_top_symbol(sym);
|
||||||
|
code_builder.i64_load(Align::Bytes8, offset + 8);
|
||||||
|
}
|
||||||
|
|
||||||
code_builder.set_top_symbol(sym);
|
code_builder.set_top_symbol(sym);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,6 +308,7 @@ impl<'a> Storage<'a> {
|
||||||
location,
|
location,
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
alignment_bytes,
|
||||||
|
format: StackMemoryFormat::Aggregate,
|
||||||
} = self.get(sym)
|
} = self.get(sym)
|
||||||
{
|
{
|
||||||
if *size == 0 {
|
if *size == 0 {
|
||||||
|
@ -334,6 +351,7 @@ impl<'a> Storage<'a> {
|
||||||
location,
|
location,
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
alignment_bytes,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
let (from_ptr, from_offset) = location.local_and_offset(self.stack_frame_pointer);
|
let (from_ptr, from_offset) = location.local_and_offset(self.stack_frame_pointer);
|
||||||
copy_memory(
|
copy_memory(
|
||||||
|
@ -390,6 +408,7 @@ impl<'a> Storage<'a> {
|
||||||
location,
|
location,
|
||||||
size,
|
size,
|
||||||
alignment_bytes,
|
alignment_bytes,
|
||||||
|
..
|
||||||
} => {
|
} => {
|
||||||
let (to_ptr, to_offset) = location.local_and_offset(self.stack_frame_pointer);
|
let (to_ptr, to_offset) = location.local_and_offset(self.stack_frame_pointer);
|
||||||
copy_memory(
|
copy_memory(
|
||||||
|
@ -490,11 +509,13 @@ impl<'a> Storage<'a> {
|
||||||
location: to_location,
|
location: to_location,
|
||||||
size: to_size,
|
size: to_size,
|
||||||
alignment_bytes: to_alignment_bytes,
|
alignment_bytes: to_alignment_bytes,
|
||||||
|
..
|
||||||
},
|
},
|
||||||
StackMemory {
|
StackMemory {
|
||||||
location: from_location,
|
location: from_location,
|
||||||
size: from_size,
|
size: from_size,
|
||||||
alignment_bytes: from_alignment_bytes,
|
alignment_bytes: from_alignment_bytes,
|
||||||
|
..
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
let (from_ptr, from_offset) =
|
let (from_ptr, from_offset) =
|
||||||
|
|
|
@ -3627,11 +3627,7 @@ fn fabricate_effects_module<'a>(
|
||||||
scope,
|
scope,
|
||||||
};
|
};
|
||||||
|
|
||||||
let constraint = constrain_module(
|
let constraint = constrain_module(&module_output.declarations, module_id);
|
||||||
&module_output.aliases,
|
|
||||||
&module_output.declarations,
|
|
||||||
module_id,
|
|
||||||
);
|
|
||||||
|
|
||||||
let module = Module {
|
let module = Module {
|
||||||
module_id,
|
module_id,
|
||||||
|
@ -3764,11 +3760,7 @@ where
|
||||||
)),
|
)),
|
||||||
};
|
};
|
||||||
|
|
||||||
let constraint = constrain_module(
|
let constraint = constrain_module(&module_output.declarations, module_id);
|
||||||
&module_output.aliases,
|
|
||||||
&module_output.declarations,
|
|
||||||
module_id,
|
|
||||||
);
|
|
||||||
|
|
||||||
let module = Module {
|
let module = Module {
|
||||||
module_id,
|
module_id,
|
||||||
|
|
|
@ -1140,8 +1140,17 @@ impl<'a> BranchInfo<'a> {
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub enum ModifyRc {
|
pub enum ModifyRc {
|
||||||
|
/// Increment a reference count
|
||||||
Inc(Symbol, u64),
|
Inc(Symbol, u64),
|
||||||
|
/// Decrement a reference count
|
||||||
Dec(Symbol),
|
Dec(Symbol),
|
||||||
|
/// A DecRef is a non-recursive reference count decrement
|
||||||
|
/// e.g. If we Dec a list of lists, then if the reference count of the outer list is one,
|
||||||
|
/// a Dec will recursively decrement all elements, then free the memory of the outer list.
|
||||||
|
/// A DecRef would just free the outer list.
|
||||||
|
/// That is dangerous because you may not free the elements, but in our Zig builtins,
|
||||||
|
/// sometimes we know we already dealt with the elements (e.g. by copying them all over
|
||||||
|
/// to a new list) and so we can just do a DecRef, which is much cheaper in such a case.
|
||||||
DecRef(Symbol),
|
DecRef(Symbol),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -358,7 +358,7 @@ fn u8_hex_int_alias() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(any(feature = "gen-llvm"))]
|
#[cfg(any(feature = "gen-llvm", feature = "gen-wasm"))]
|
||||||
fn dec_float_alias() {
|
fn dec_float_alias() {
|
||||||
assert_evals_to!(
|
assert_evals_to!(
|
||||||
indoc!(
|
indoc!(
|
||||||
|
|
|
@ -5,6 +5,9 @@ use roc_can::builtins::builtin_defs_map;
|
||||||
use roc_collections::all::MutMap;
|
use roc_collections::all::MutMap;
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use roc_mono::ir::PRETTY_PRINT_IR_SYMBOLS;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn promote_expr_to_module(src: &str) -> String {
|
fn promote_expr_to_module(src: &str) -> String {
|
||||||
let mut buffer = String::from("app \"test\" provides [ main ] to \"./platform\"\n\nmain =\n");
|
let mut buffer = String::from("app \"test\" provides [ main ] to \"./platform\"\n\nmain =\n");
|
||||||
|
@ -77,7 +80,14 @@ pub fn helper(
|
||||||
// while you're working on the dev backend!
|
// while you're working on the dev backend!
|
||||||
{
|
{
|
||||||
// println!("=========== Procedures ==========");
|
// println!("=========== Procedures ==========");
|
||||||
// println!("{:?}", procedures);
|
// if PRETTY_PRINT_IR_SYMBOLS {
|
||||||
|
// println!("");
|
||||||
|
// for proc in procedures.values() {
|
||||||
|
// println!("{}", proc.to_pretty(200));
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// println!("{:?}", procedures.values());
|
||||||
|
// }
|
||||||
// println!("=================================\n");
|
// println!("=================================\n");
|
||||||
|
|
||||||
// println!("=========== Interns ==========");
|
// println!("=========== Interns ==========");
|
||||||
|
|
|
@ -17,6 +17,9 @@ use roc_gen_wasm::wasm_module::{
|
||||||
};
|
};
|
||||||
use roc_gen_wasm::MEMORY_NAME;
|
use roc_gen_wasm::MEMORY_NAME;
|
||||||
|
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use roc_mono::ir::PRETTY_PRINT_IR_SYMBOLS;
|
||||||
|
|
||||||
const TEST_WRAPPER_NAME: &str = "test_wrapper";
|
const TEST_WRAPPER_NAME: &str = "test_wrapper";
|
||||||
|
|
||||||
std::thread_local! {
|
std::thread_local! {
|
||||||
|
@ -84,9 +87,16 @@ pub fn helper_wasm<'a, T: Wasm32TestResult>(
|
||||||
|
|
||||||
// You can comment and uncomment this block out to get more useful information
|
// You can comment and uncomment this block out to get more useful information
|
||||||
// while you're working on the wasm backend!
|
// while you're working on the wasm backend!
|
||||||
// {
|
{
|
||||||
// println!("=========== Procedures ==========");
|
// println!("=========== Procedures ==========");
|
||||||
// println!("{:?}", procedures);
|
// if PRETTY_PRINT_IR_SYMBOLS {
|
||||||
|
// println!("");
|
||||||
|
// for proc in procedures.values() {
|
||||||
|
// println!("{}", proc.to_pretty(200));
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// println!("{:?}", procedures.values());
|
||||||
|
// }
|
||||||
// println!("=================================\n");
|
// println!("=================================\n");
|
||||||
|
|
||||||
// println!("=========== Interns ==========");
|
// println!("=========== Interns ==========");
|
||||||
|
@ -96,7 +106,7 @@ pub fn helper_wasm<'a, T: Wasm32TestResult>(
|
||||||
// println!("=========== Exposed ==========");
|
// println!("=========== Exposed ==========");
|
||||||
// println!("{:?}", exposed_to_host);
|
// println!("{:?}", exposed_to_host);
|
||||||
// println!("=================================\n");
|
// println!("=================================\n");
|
||||||
// }
|
}
|
||||||
|
|
||||||
debug_assert_eq!(exposed_to_host.len(), 1);
|
debug_assert_eq!(exposed_to_host.len(), 1);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue