Merge remote-tracking branch 'origin/trunk' into layout-builtin-numbers-refactor

This commit is contained in:
Folkert 2021-11-21 23:19:55 +01:00
commit f96d60a13e
9 changed files with 108 additions and 46 deletions

View file

@ -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)
} }

View file

@ -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);

View file

@ -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(

View file

@ -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) =

View file

@ -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,

View file

@ -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),
} }

View file

@ -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!(

View file

@ -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 ==========");

View file

@ -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,19 +87,26 @@ 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!("=================================\n"); // println!("");
// for proc in procedures.values() {
// println!("{}", proc.to_pretty(200));
// }
// } else {
// println!("{:?}", procedures.values());
// }
// println!("=================================\n");
// println!("=========== Interns =========="); // println!("=========== Interns ==========");
// println!("{:?}", interns); // println!("{:?}", interns);
// println!("=================================\n"); // println!("=================================\n");
// 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);