mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-29 14:54:47 +00:00
Reorganise Wasm lowlevels to get pointer equality working correctly
This commit is contained in:
parent
ece28f1975
commit
c510226c15
3 changed files with 165 additions and 157 deletions
|
@ -11,13 +11,10 @@ use crate::wasm_module::{Align, CodeBuilder, ValueType::*};
|
|||
pub enum LowlevelBuildResult {
|
||||
Done,
|
||||
BuiltinCall(&'static str),
|
||||
SpecializedEq,
|
||||
SpecializedNotEq,
|
||||
SpecializedHash,
|
||||
NotImplemented,
|
||||
}
|
||||
|
||||
pub fn decode_low_level<'a>(
|
||||
pub fn dispatch_low_level<'a>(
|
||||
code_builder: &mut CodeBuilder<'a>,
|
||||
storage: &mut Storage<'a>,
|
||||
lowlevel: LowLevel,
|
||||
|
@ -509,109 +506,15 @@ pub fn decode_low_level<'a>(
|
|||
WasmLayout::StackMemory { .. } => return NotImplemented,
|
||||
}
|
||||
}
|
||||
Eq => {
|
||||
use StoredValue::*;
|
||||
match storage.get(&args[0]).to_owned() {
|
||||
VirtualMachineStack { value_type, .. } | Local { value_type, .. } => {
|
||||
match value_type {
|
||||
I32 => code_builder.i32_eq(),
|
||||
I64 => code_builder.i64_eq(),
|
||||
F32 => code_builder.f32_eq(),
|
||||
F64 => code_builder.f64_eq(),
|
||||
}
|
||||
}
|
||||
StackMemory {
|
||||
format,
|
||||
location: location0,
|
||||
..
|
||||
} => {
|
||||
if let StackMemory {
|
||||
location: location1,
|
||||
..
|
||||
} = storage.get(&args[1]).to_owned()
|
||||
{
|
||||
let stack_frame_pointer = storage.stack_frame_pointer;
|
||||
let compare_bytes = |code_builder: &mut CodeBuilder| {
|
||||
let (local0, offset0) = location0.local_and_offset(stack_frame_pointer);
|
||||
let (local1, offset1) = location1.local_and_offset(stack_frame_pointer);
|
||||
|
||||
code_builder.get_local(local0);
|
||||
code_builder.i64_load(Align::Bytes8, offset0);
|
||||
code_builder.get_local(local1);
|
||||
code_builder.i64_load(Align::Bytes8, offset1);
|
||||
code_builder.i64_eq();
|
||||
|
||||
code_builder.get_local(local0);
|
||||
code_builder.i64_load(Align::Bytes8, offset0 + 8);
|
||||
code_builder.get_local(local1);
|
||||
code_builder.i64_load(Align::Bytes8, offset1 + 8);
|
||||
code_builder.i64_eq();
|
||||
|
||||
code_builder.i32_and();
|
||||
};
|
||||
|
||||
match format {
|
||||
Decimal => {
|
||||
// Both args are finite
|
||||
let first = [args[0]];
|
||||
let second = [args[1]];
|
||||
decode_low_level(
|
||||
code_builder,
|
||||
storage,
|
||||
LowLevel::NumIsFinite,
|
||||
&first,
|
||||
ret_layout,
|
||||
);
|
||||
decode_low_level(
|
||||
code_builder,
|
||||
storage,
|
||||
LowLevel::NumIsFinite,
|
||||
&second,
|
||||
ret_layout,
|
||||
);
|
||||
code_builder.i32_and();
|
||||
|
||||
// AND they have the same bytes
|
||||
compare_bytes(code_builder);
|
||||
code_builder.i32_and();
|
||||
}
|
||||
Int128 => compare_bytes(code_builder),
|
||||
Float128 => return NotImplemented,
|
||||
DataStructure => return SpecializedEq,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
NotEq => match storage.get(&args[0]) {
|
||||
StoredValue::VirtualMachineStack { value_type, .. }
|
||||
| StoredValue::Local { value_type, .. } => match value_type {
|
||||
I32 => code_builder.i32_ne(),
|
||||
I64 => code_builder.i64_ne(),
|
||||
F32 => code_builder.f32_ne(),
|
||||
F64 => code_builder.f64_ne(),
|
||||
},
|
||||
StoredValue::StackMemory { format, .. } => {
|
||||
if matches!(format, DataStructure) {
|
||||
return SpecializedNotEq;
|
||||
} else {
|
||||
decode_low_level(code_builder, storage, LowLevel::Eq, args, ret_layout);
|
||||
code_builder.i32_eqz();
|
||||
}
|
||||
}
|
||||
},
|
||||
And => code_builder.i32_and(),
|
||||
Or => code_builder.i32_or(),
|
||||
Not => code_builder.i32_eqz(),
|
||||
Hash => return SpecializedHash,
|
||||
ExpectTrue => return NotImplemented,
|
||||
PtrCast => {
|
||||
// We don't need any instructions here, since we've already loaded the value.
|
||||
// PtrCast just creates separate Symbols and Layouts for the argument and return value.
|
||||
// This is used for pointer math in refcounting and for pointer equality
|
||||
}
|
||||
RefCountInc => return BuiltinCall(bitcode::UTILS_INCREF),
|
||||
RefCountDec => return BuiltinCall(bitcode::UTILS_DECREF),
|
||||
Eq | NotEq | Hash | PtrCast => {
|
||||
internal_error!("{:?} should be handled in backend.rs", lowlevel)
|
||||
}
|
||||
}
|
||||
Done
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue