mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-28 06:14:46 +00:00
Merge branch 'trunk' of github.com:rtfeldman/roc into wasm-tags
This commit is contained in:
commit
3f7b3bef87
13 changed files with 559 additions and 131 deletions
|
@ -7,6 +7,7 @@ use roc_module::symbol::{Interns, Symbol};
|
|||
use roc_mono::gen_refcount::{RefcountProcGenerator, REFCOUNT_MAX};
|
||||
use roc_mono::ir::{CallType, Expr, JoinPointId, Literal, Proc, Stmt};
|
||||
use roc_mono::layout::{Builtin, Layout, LayoutIds, TagIdIntType, UnionLayout};
|
||||
use roc_reporting::internal_error;
|
||||
|
||||
use crate::layout::{CallConv, ReturnMethod, WasmLayout};
|
||||
use crate::low_level::{decode_low_level, LowlevelBuildResult};
|
||||
|
@ -200,19 +201,17 @@ impl<'a> WasmBackend<'a> {
|
|||
|
||||
***********************************************************/
|
||||
|
||||
pub fn build_proc(&mut self, proc: &Proc<'a>) -> Result<(), String> {
|
||||
pub fn build_proc(&mut self, proc: &Proc<'a>) {
|
||||
// println!("\ngenerating procedure {:?}\n", proc.name);
|
||||
|
||||
self.start_proc(proc);
|
||||
|
||||
self.build_stmt(&proc.body, &proc.ret_layout)?;
|
||||
self.build_stmt(&proc.body, &proc.ret_layout);
|
||||
|
||||
self.finalize_proc()?;
|
||||
self.finalize_proc();
|
||||
self.reset();
|
||||
|
||||
// println!("\nfinished generating {:?}\n", proc.name);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn start_proc(&mut self, proc: &Proc<'a>) {
|
||||
|
@ -243,7 +242,7 @@ impl<'a> WasmBackend<'a> {
|
|||
});
|
||||
}
|
||||
|
||||
fn finalize_proc(&mut self) -> Result<(), String> {
|
||||
fn finalize_proc(&mut self) {
|
||||
// end the block from start_proc, to ensure all paths pop stack memory (if any)
|
||||
self.end_block();
|
||||
|
||||
|
@ -253,8 +252,6 @@ impl<'a> WasmBackend<'a> {
|
|||
self.storage.stack_frame_size,
|
||||
self.storage.stack_frame_pointer,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
|
@ -278,7 +275,7 @@ impl<'a> WasmBackend<'a> {
|
|||
self.code_builder.end();
|
||||
}
|
||||
|
||||
fn build_stmt(&mut self, stmt: &Stmt<'a>, ret_layout: &Layout<'a>) -> Result<(), String> {
|
||||
fn build_stmt(&mut self, stmt: &Stmt<'a>, ret_layout: &Layout<'a>) {
|
||||
match stmt {
|
||||
Stmt::Let(_, _, _, _) => {
|
||||
let mut current_stmt = stmt;
|
||||
|
@ -294,7 +291,7 @@ impl<'a> WasmBackend<'a> {
|
|||
|
||||
let sym_storage = self.storage.allocate(&wasm_layout, *sym, kind);
|
||||
|
||||
self.build_expr(sym, expr, layout, &sym_storage)?;
|
||||
self.build_expr(sym, expr, layout, &sym_storage);
|
||||
|
||||
// If this value is stored in the VM stack, we need code_builder to track it
|
||||
// (since every instruction can change the VM stack)
|
||||
|
@ -309,8 +306,7 @@ impl<'a> WasmBackend<'a> {
|
|||
current_stmt = *following;
|
||||
}
|
||||
|
||||
self.build_stmt(current_stmt, ret_layout)?;
|
||||
Ok(())
|
||||
self.build_stmt(current_stmt, ret_layout);
|
||||
}
|
||||
|
||||
Stmt::Ret(sym) => {
|
||||
|
@ -346,8 +342,6 @@ impl<'a> WasmBackend<'a> {
|
|||
}
|
||||
// jump to the "stack frame pop" code at the end of the function
|
||||
self.code_builder.br(self.block_depth - 1);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Stmt::Switch {
|
||||
|
@ -415,7 +409,7 @@ impl<'a> WasmBackend<'a> {
|
|||
}
|
||||
|
||||
// if we never jumped because a value matched, we're in the default case
|
||||
self.build_stmt(default_branch.1, ret_layout)?;
|
||||
self.build_stmt(default_branch.1, ret_layout);
|
||||
|
||||
// now put in the actual body of each branch in order
|
||||
// (the first branch would have broken out of 1 block,
|
||||
|
@ -423,10 +417,8 @@ impl<'a> WasmBackend<'a> {
|
|||
for (_, _, branch) in branches.iter() {
|
||||
self.end_block();
|
||||
|
||||
self.build_stmt(branch, ret_layout)?;
|
||||
self.build_stmt(branch, ret_layout);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Stmt::Join {
|
||||
id,
|
||||
|
@ -456,7 +448,7 @@ impl<'a> WasmBackend<'a> {
|
|||
self.joinpoint_label_map
|
||||
.insert(*id, (self.block_depth, jp_param_storages));
|
||||
|
||||
self.build_stmt(remainder, ret_layout)?;
|
||||
self.build_stmt(remainder, ret_layout);
|
||||
|
||||
self.end_block();
|
||||
|
||||
|
@ -469,12 +461,10 @@ impl<'a> WasmBackend<'a> {
|
|||
};
|
||||
self.start_loop(loop_block_type);
|
||||
|
||||
self.build_stmt(body, ret_layout)?;
|
||||
self.build_stmt(body, ret_layout);
|
||||
|
||||
// ends the loop
|
||||
self.end_block();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Stmt::Jump(id, arguments) => {
|
||||
let (target, param_storages) = self.joinpoint_label_map[id].clone();
|
||||
|
@ -492,8 +482,6 @@ impl<'a> WasmBackend<'a> {
|
|||
// jump
|
||||
let levels = self.block_depth - target;
|
||||
self.code_builder.br(levels);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Stmt::Refcounting(modify, following) => {
|
||||
|
@ -535,11 +523,10 @@ impl<'a> WasmBackend<'a> {
|
|||
}));
|
||||
}
|
||||
|
||||
self.build_stmt(&rc_stmt, ret_layout)?;
|
||||
Ok(())
|
||||
self.build_stmt(&rc_stmt, ret_layout);
|
||||
}
|
||||
|
||||
x => Err(format!("statement not yet implemented: {:?}", x)),
|
||||
x => todo!("statement {:?}", x),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -555,7 +542,7 @@ impl<'a> WasmBackend<'a> {
|
|||
expr: &Expr<'a>,
|
||||
layout: &Layout<'a>,
|
||||
storage: &StoredValue,
|
||||
) -> Result<(), String> {
|
||||
) {
|
||||
let wasm_layout = WasmLayout::new(layout);
|
||||
match expr {
|
||||
Expr::Literal(lit) => self.load_literal(lit, storage, *sym, layout),
|
||||
|
@ -591,13 +578,14 @@ impl<'a> WasmBackend<'a> {
|
|||
num_wasm_args,
|
||||
has_return_val,
|
||||
);
|
||||
return Ok(());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
unreachable!(
|
||||
internal_error!(
|
||||
"Could not find procedure {:?}\nKnown procedures: {:?}",
|
||||
func_sym, self.proc_symbols
|
||||
func_sym,
|
||||
self.proc_symbols
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -605,7 +593,7 @@ impl<'a> WasmBackend<'a> {
|
|||
self.build_low_level(*lowlevel, arguments, *sym, wasm_layout)
|
||||
}
|
||||
|
||||
x => Err(format!("the call type, {:?}, is not yet implemented", x)),
|
||||
x => todo!("call type {:?}", x),
|
||||
},
|
||||
|
||||
Expr::Struct(fields) => self.create_struct(sym, layout, fields),
|
||||
|
@ -628,12 +616,11 @@ impl<'a> WasmBackend<'a> {
|
|||
offset,
|
||||
);
|
||||
} else {
|
||||
unreachable!("Unexpected storage for {:?}", structure)
|
||||
internal_error!("Unexpected storage for {:?}", structure)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Expr::Array { .. } => Err(format!("Expression is not yet implemented {:?}", expr)),
|
||||
Expr::Array { .. } => todo!("Expression {:?}", expr),
|
||||
|
||||
Expr::EmptyArray => {
|
||||
if let StoredValue::StackMemory { location, .. } = storage {
|
||||
|
@ -646,10 +633,8 @@ impl<'a> WasmBackend<'a> {
|
|||
self.code_builder.get_local(local_id);
|
||||
self.code_builder.i64_const(0);
|
||||
self.code_builder.i64_store(Align::Bytes4, offset);
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
unreachable!("Unexpected storage for {:?}", sym)
|
||||
internal_error!("Unexpected storage for {:?}", sym)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -658,12 +643,9 @@ impl<'a> WasmBackend<'a> {
|
|||
tag_id,
|
||||
arguments,
|
||||
..
|
||||
} => {
|
||||
self.build_tag(tag_layout, *tag_id, arguments, storage);
|
||||
Ok(())
|
||||
}
|
||||
} => self.build_tag(tag_layout, *tag_id, arguments, storage),
|
||||
|
||||
x => Err(format!("Expression is not yet implemented {:?}", x)),
|
||||
x => todo!("Expression {:?}", x),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -679,7 +661,7 @@ impl<'a> WasmBackend<'a> {
|
|||
let (local_id, offset) = if let StoredValue::StackMemory { location, .. } = stored {
|
||||
location.local_and_offset(self.storage.stack_frame_pointer)
|
||||
} else {
|
||||
panic!("NonRecursive Tag should always be stored in StackMemory");
|
||||
internal_error!("NonRecursive Tag should always be stored in StackMemory");
|
||||
};
|
||||
|
||||
let mut field_offset = offset;
|
||||
|
@ -710,7 +692,7 @@ impl<'a> WasmBackend<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
_ => unimplemented!("Tag with layout {:?}", union_layout),
|
||||
_ => todo!("Tag with layout {:?}", union_layout),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -720,7 +702,7 @@ impl<'a> WasmBackend<'a> {
|
|||
arguments: &'a [Symbol],
|
||||
return_sym: Symbol,
|
||||
return_layout: WasmLayout,
|
||||
) -> Result<(), String> {
|
||||
) {
|
||||
let (param_types, ret_type) = self.storage.load_symbols_for_call(
|
||||
self.env.arena,
|
||||
&mut self.code_builder,
|
||||
|
@ -740,15 +722,13 @@ impl<'a> WasmBackend<'a> {
|
|||
use LowlevelBuildResult::*;
|
||||
|
||||
match build_result {
|
||||
Done => Ok(()),
|
||||
Done => {}
|
||||
BuiltinCall(name) => {
|
||||
self.call_zig_builtin(name, param_types, ret_type);
|
||||
Ok(())
|
||||
}
|
||||
NotImplemented => Err(format!(
|
||||
"Low level operation {:?} is not yet implemented",
|
||||
lowlevel
|
||||
)),
|
||||
NotImplemented => {
|
||||
todo!("Low level operation {:?}", lowlevel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -758,8 +738,8 @@ impl<'a> WasmBackend<'a> {
|
|||
storage: &StoredValue,
|
||||
sym: Symbol,
|
||||
layout: &Layout<'a>,
|
||||
) -> Result<(), String> {
|
||||
let not_supported_error = || panic!("Literal value {:?} is not yet implemented", lit);
|
||||
) {
|
||||
let not_supported_error = || todo!("Literal value {:?}", lit);
|
||||
|
||||
match storage {
|
||||
StoredValue::VirtualMachineStack { value_type, .. } => {
|
||||
|
@ -770,9 +750,7 @@ impl<'a> WasmBackend<'a> {
|
|||
(Literal::Int(x), ValueType::I32) => self.code_builder.i32_const(*x as i32),
|
||||
(Literal::Bool(x), ValueType::I32) => self.code_builder.i32_const(*x as i32),
|
||||
(Literal::Byte(x), ValueType::I32) => self.code_builder.i32_const(*x as i32),
|
||||
_ => {
|
||||
return not_supported_error();
|
||||
}
|
||||
_ => not_supported_error(),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -822,16 +800,11 @@ impl<'a> WasmBackend<'a> {
|
|||
self.code_builder.i32_store(Align::Bytes4, offset + 4);
|
||||
};
|
||||
}
|
||||
_ => {
|
||||
return not_supported_error();
|
||||
}
|
||||
_ => not_supported_error(),
|
||||
},
|
||||
|
||||
_ => {
|
||||
return not_supported_error();
|
||||
}
|
||||
_ => not_supported_error(),
|
||||
};
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Look up a string constant in our internal data structures
|
||||
|
@ -852,9 +825,10 @@ impl<'a> WasmBackend<'a> {
|
|||
let elements_addr = *segment_offset + CONST_SEGMENT_BASE_ADDR;
|
||||
(*linker_sym_index as u32, elements_addr)
|
||||
}
|
||||
_ => unreachable!(
|
||||
_ => internal_error!(
|
||||
"Compiler bug: Invalid linker symbol info for string {:?}:\n{:?}",
|
||||
string, syminfo
|
||||
string,
|
||||
syminfo
|
||||
),
|
||||
}
|
||||
}
|
||||
|
@ -894,12 +868,7 @@ impl<'a> WasmBackend<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn create_struct(
|
||||
&mut self,
|
||||
sym: &Symbol,
|
||||
layout: &Layout<'a>,
|
||||
fields: &'a [Symbol],
|
||||
) -> Result<(), String> {
|
||||
fn create_struct(&mut self, sym: &Symbol, layout: &Layout<'a>, fields: &'a [Symbol]) {
|
||||
// TODO: we just calculated storage and now we're getting it out of a map
|
||||
// Not passing it as an argument because I'm trying to match Backend method signatures
|
||||
let storage = self.storage.get(sym).to_owned();
|
||||
|
@ -922,15 +891,9 @@ impl<'a> WasmBackend<'a> {
|
|||
} else {
|
||||
// Zero-size struct. No code to emit.
|
||||
// These values are purely conceptual, they only exist internally in the compiler
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return Err(format!(
|
||||
"Cannot create struct {:?} with storage {:?}",
|
||||
sym, storage
|
||||
));
|
||||
}
|
||||
_ => internal_error!("Cannot create struct {:?} with storage {:?}", sym, storage),
|
||||
};
|
||||
} else {
|
||||
// Struct expression but not Struct layout => single element. Copy it.
|
||||
|
@ -938,7 +901,6 @@ impl<'a> WasmBackend<'a> {
|
|||
self.storage
|
||||
.clone_value(&mut self.code_builder, &storage, &field_storage, fields[0]);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generate a call instruction to a Zig builtin function.
|
||||
|
@ -958,7 +920,7 @@ impl<'a> WasmBackend<'a> {
|
|||
SymInfo::Function(WasmObjectSymbol::Imported { index, .. }) => {
|
||||
(*index, *sym_idx as u32)
|
||||
}
|
||||
x => unreachable!("Invalid linker symbol for builtin {}: {:?}", name, x),
|
||||
x => internal_error!("Invalid linker symbol for builtin {}: {:?}", name, x),
|
||||
},
|
||||
|
||||
None => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue