mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 08:11:12 +00:00
Wasm: Refactor lowlevels to get more flexibility without increasing boilerplate.
This commit is contained in:
parent
88b779c3ff
commit
f635dd8776
2 changed files with 669 additions and 642 deletions
|
@ -16,7 +16,7 @@ use roc_mono::layout::{Builtin, Layout, LayoutIds, TagIdIntType, UnionLayout};
|
||||||
use roc_reporting::internal_error;
|
use roc_reporting::internal_error;
|
||||||
|
|
||||||
use crate::layout::{CallConv, ReturnMethod, StackMemoryFormat, WasmLayout};
|
use crate::layout::{CallConv, ReturnMethod, StackMemoryFormat, WasmLayout};
|
||||||
use crate::low_level::{dispatch_low_level, LowlevelBuildResult};
|
use crate::low_level::LowLevelCall;
|
||||||
use crate::storage::{StackMemoryLocation, Storage, StoredValue, StoredValueKind};
|
use crate::storage::{StackMemoryLocation, Storage, StoredValue, StoredValueKind};
|
||||||
use crate::wasm_module::linking::{DataSymbol, LinkingSegment, WasmObjectSymbol};
|
use crate::wasm_module::linking::{DataSymbol, LinkingSegment, WasmObjectSymbol};
|
||||||
use crate::wasm_module::sections::{DataMode, DataSegment};
|
use crate::wasm_module::sections::{DataMode, DataSegment};
|
||||||
|
@ -35,7 +35,7 @@ use crate::{
|
||||||
const CONST_SEGMENT_BASE_ADDR: u32 = 1024;
|
const CONST_SEGMENT_BASE_ADDR: u32 = 1024;
|
||||||
|
|
||||||
pub struct WasmBackend<'a> {
|
pub struct WasmBackend<'a> {
|
||||||
env: &'a Env<'a>,
|
pub env: &'a Env<'a>,
|
||||||
interns: &'a mut Interns,
|
interns: &'a mut Interns,
|
||||||
|
|
||||||
// Module-level data
|
// Module-level data
|
||||||
|
@ -48,8 +48,8 @@ pub struct WasmBackend<'a> {
|
||||||
helper_proc_gen: CodeGenHelp<'a>,
|
helper_proc_gen: CodeGenHelp<'a>,
|
||||||
|
|
||||||
// Function-level data
|
// Function-level data
|
||||||
code_builder: CodeBuilder<'a>,
|
pub code_builder: CodeBuilder<'a>,
|
||||||
storage: Storage<'a>,
|
pub storage: Storage<'a>,
|
||||||
|
|
||||||
/// how many blocks deep are we (used for jumps)
|
/// how many blocks deep are we (used for jumps)
|
||||||
block_depth: u32,
|
block_depth: u32,
|
||||||
|
@ -805,21 +805,21 @@ impl<'a> WasmBackend<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
lowlevel: LowLevel,
|
lowlevel: LowLevel,
|
||||||
arguments: &'a [Symbol],
|
arguments: &'a [Symbol],
|
||||||
return_sym: Symbol,
|
ret_symbol: Symbol,
|
||||||
mono_layout: &Layout<'a>,
|
ret_layout: &Layout<'a>,
|
||||||
storage: &StoredValue,
|
ret_storage: &StoredValue,
|
||||||
) {
|
) {
|
||||||
use LowLevel::*;
|
use LowLevel::*;
|
||||||
let return_layout = WasmLayout::new(mono_layout);
|
let wasm_layout = WasmLayout::new(ret_layout);
|
||||||
|
|
||||||
match lowlevel {
|
match lowlevel {
|
||||||
Eq | NotEq => self.build_eq_or_neq(
|
Eq | NotEq => self.build_eq_or_neq(
|
||||||
lowlevel,
|
lowlevel,
|
||||||
arguments,
|
arguments,
|
||||||
return_sym,
|
ret_symbol,
|
||||||
return_layout,
|
wasm_layout,
|
||||||
mono_layout,
|
ret_layout,
|
||||||
storage,
|
ret_storage,
|
||||||
),
|
),
|
||||||
PtrCast => {
|
PtrCast => {
|
||||||
// Don't want Zig calling convention when casting pointers.
|
// Don't want Zig calling convention when casting pointers.
|
||||||
|
@ -829,37 +829,14 @@ impl<'a> WasmBackend<'a> {
|
||||||
|
|
||||||
// Almost all lowlevels take this branch, except for the special cases above
|
// Almost all lowlevels take this branch, except for the special cases above
|
||||||
_ => {
|
_ => {
|
||||||
// Load the arguments using Zig calling convention
|
let low_level_call = LowLevelCall {
|
||||||
let (param_types, ret_type) = self.storage.load_symbols_for_call(
|
|
||||||
self.env.arena,
|
|
||||||
&mut self.code_builder,
|
|
||||||
arguments,
|
|
||||||
return_sym,
|
|
||||||
&return_layout,
|
|
||||||
CallConv::Zig,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Generate instructions OR decide which Zig function to call
|
|
||||||
let build_result = dispatch_low_level(
|
|
||||||
&mut self.code_builder,
|
|
||||||
&mut self.storage,
|
|
||||||
lowlevel,
|
lowlevel,
|
||||||
arguments,
|
arguments,
|
||||||
&return_layout,
|
ret_symbol,
|
||||||
mono_layout,
|
ret_layout: ret_layout.to_owned(),
|
||||||
);
|
ret_storage: ret_storage.to_owned(),
|
||||||
|
};
|
||||||
// Handle the result
|
low_level_call.generate(self);
|
||||||
use LowlevelBuildResult::*;
|
|
||||||
match build_result {
|
|
||||||
Done => {}
|
|
||||||
BuiltinCall(name) => {
|
|
||||||
self.expr_call_zig_builtin(name, param_types, ret_type);
|
|
||||||
}
|
|
||||||
NotImplemented => {
|
|
||||||
todo!("Low level operation {:?}", lowlevel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -867,7 +844,7 @@ impl<'a> WasmBackend<'a> {
|
||||||
/// Generate a call instruction to a Zig builtin function.
|
/// Generate a call instruction to a Zig builtin function.
|
||||||
/// And if we haven't seen it before, add an Import and linker data for it.
|
/// And if we haven't seen it before, add an Import and linker data for it.
|
||||||
/// Zig calls use LLVM's "fast" calling convention rather than our usual C ABI.
|
/// Zig calls use LLVM's "fast" calling convention rather than our usual C ABI.
|
||||||
fn expr_call_zig_builtin(
|
pub fn call_zig_builtin_after_loading_args(
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
param_types: Vec<'a, ValueType>,
|
param_types: Vec<'a, ValueType>,
|
||||||
|
@ -992,7 +969,7 @@ impl<'a> WasmBackend<'a> {
|
||||||
// Call the foreign function. (Zig and C calling conventions are the same for this signature)
|
// Call the foreign function. (Zig and C calling conventions are the same for this signature)
|
||||||
let param_types = bumpalo::vec![in self.env.arena; ValueType::I32, ValueType::I32];
|
let param_types = bumpalo::vec![in self.env.arena; ValueType::I32, ValueType::I32];
|
||||||
let ret_type = Some(ValueType::I32);
|
let ret_type = Some(ValueType::I32);
|
||||||
self.expr_call_zig_builtin("roc_alloc", param_types, ret_type);
|
self.call_zig_builtin_after_loading_args("roc_alloc", param_types, ret_type);
|
||||||
|
|
||||||
// Save the allocation address to a temporary local variable
|
// Save the allocation address to a temporary local variable
|
||||||
let local_id = self.storage.create_anonymous_local(ValueType::I32);
|
let local_id = self.storage.create_anonymous_local(ValueType::I32);
|
||||||
|
@ -1368,7 +1345,7 @@ impl<'a> WasmBackend<'a> {
|
||||||
&return_layout,
|
&return_layout,
|
||||||
CallConv::Zig,
|
CallConv::Zig,
|
||||||
);
|
);
|
||||||
self.expr_call_zig_builtin(bitcode::STR_EQUAL, param_types, ret_type);
|
self.call_zig_builtin_after_loading_args(bitcode::STR_EQUAL, param_types, ret_type);
|
||||||
if matches!(lowlevel, LowLevel::NotEq) {
|
if matches!(lowlevel, LowLevel::NotEq) {
|
||||||
self.code_builder.i32_eqz();
|
self.code_builder.i32_eqz();
|
||||||
}
|
}
|
||||||
|
@ -1472,22 +1449,25 @@ impl<'a> WasmBackend<'a> {
|
||||||
// Both args are finite
|
// Both args are finite
|
||||||
let first = [arguments[0]];
|
let first = [arguments[0]];
|
||||||
let second = [arguments[1]];
|
let second = [arguments[1]];
|
||||||
dispatch_low_level(
|
|
||||||
&mut self.code_builder,
|
// TODO!
|
||||||
&mut self.storage,
|
//
|
||||||
LowLevel::NumIsFinite,
|
// dispatch_low_level(
|
||||||
&first,
|
// &mut self.code_builder,
|
||||||
&return_layout,
|
// &mut self.storage,
|
||||||
mono_layout,
|
// LowLevel::NumIsFinite,
|
||||||
);
|
// &first,
|
||||||
dispatch_low_level(
|
// &return_layout,
|
||||||
&mut self.code_builder,
|
// mono_layout,
|
||||||
&mut self.storage,
|
// );
|
||||||
LowLevel::NumIsFinite,
|
// dispatch_low_level(
|
||||||
&second,
|
// &mut self.code_builder,
|
||||||
&return_layout,
|
// &mut self.storage,
|
||||||
mono_layout,
|
// LowLevel::NumIsFinite,
|
||||||
);
|
// &second,
|
||||||
|
// &return_layout,
|
||||||
|
// mono_layout,
|
||||||
|
// );
|
||||||
self.code_builder.i32_and();
|
self.code_builder.i32_and();
|
||||||
|
|
||||||
// AND they have the same bytes
|
// AND they have the same bytes
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue