From 32e5eb25708f03ffd7b59d190331fa813cf8184b Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Mon, 21 Nov 2022 18:09:58 -0800 Subject: [PATCH] WIP. --- src/backend/binaryen.rs | 74 ++++++++++++ src/backend/lower.rs | 261 +++++++++++++++++++++++++++++++++++----- src/lib.rs | 2 +- src/ops.rs | 17 +-- 4 files changed, 319 insertions(+), 35 deletions(-) diff --git a/src/backend/binaryen.rs b/src/backend/binaryen.rs index b771959..fefc34e 100644 --- a/src/backend/binaryen.rs +++ b/src/backend/binaryen.rs @@ -2,6 +2,7 @@ use crate::entity::EntityRef; use crate::ir; +use crate::{Ieee32, Ieee64}; use anyhow::{bail, Result}; use lazy_static::lazy_static; use libc::{c_char, c_void}; @@ -425,6 +426,59 @@ impl Expression { }; Expression(module.0, expr) } + + pub fn load( + module: &Module, + bytes: u8, + signed: bool, + offset: u32, + align: u32, + ty: ir::Type, + ptr: Expression, + mem: ir::Memory, + ) -> Expression { + assert_eq!(mem.index(), 0); + let ty = Type::from(ty).to_binaryen(); + let expr = + unsafe { BinaryenLoad(module.0, bytes as u32, signed, offset, align, ty, ptr.1) }; + Expression(module.0, expr) + } + + pub fn store( + module: &Module, + bytes: u8, + offset: u32, + align: u32, + ty: ir::Type, + ptr: Expression, + value: Expression, + mem: ir::Memory, + ) -> Expression { + assert_eq!(mem.index(), 0); + let ty = Type::from(ty).to_binaryen(); + let expr = + unsafe { BinaryenStore(module.0, bytes as u32, offset, align, ptr.1, value.1, ty) }; + Expression(module.0, expr) + } + + pub fn const_i32(module: &Module, value: i32) -> Expression { + let expr = unsafe { BinaryenConst(module.0, BinaryenLiteralInt32(value)) }; + Expression(module.0, expr) + } + pub fn const_i64(module: &Module, value: i64) -> Expression { + let expr = unsafe { BinaryenConst(module.0, BinaryenLiteralInt64(value)) }; + Expression(module.0, expr) + } + pub fn const_f32(module: &Module, value: Ieee32) -> Expression { + let expr = + unsafe { BinaryenConst(module.0, BinaryenLiteralFloat32Bits(value.bits() as i32)) }; + Expression(module.0, expr) + } + pub fn const_f64(module: &Module, value: Ieee64) -> Expression { + let expr = + unsafe { BinaryenConst(module.0, BinaryenLiteralFloat64Bits(value.bits() as i64)) }; + Expression(module.0, expr) + } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -782,6 +836,26 @@ extern "C" { param_type: BinaryenType, ret_type: BinaryenType, ) -> BinaryenExpression; + fn BinaryenLoad( + module: BinaryenModule, + bytes: u32, + signed: bool, + offset: u32, + align: u32, + ty: BinaryenType, + ptr: BinaryenExpression, + ) -> BinaryenExpression; + fn BinaryenStore( + module: BinaryenModule, + bytes: u32, + offset: u32, + align: u32, + ptr: BinaryenExpression, + value: BinaryenExpression, + ty: BinaryenType, + ) -> BinaryenExpression; + fn BinaryenMemorySize(module: BinaryenModule) -> BinaryenExpression; + fn BinaryenMemoryGrow(module: BinaryenModule, expr: BinaryenExpression) -> BinaryenExpression; fn BinaryenAddFunc( module: BinaryenModule, diff --git a/src/backend/lower.rs b/src/backend/lower.rs index 81459db..a3f0659 100644 --- a/src/backend/lower.rs +++ b/src/backend/lower.rs @@ -289,35 +289,242 @@ impl<'a> ElabCtx<'a> { binaryen::Expression::global_set(into_mod, global_index, args[0]) } - Operator::I32Load { memory } => todo!(), - Operator::I64Load { memory } => todo!(), - Operator::F32Load { memory } => todo!(), - Operator::F64Load { memory } => todo!(), - Operator::I32Load8S { memory } => todo!(), - Operator::I32Load8U { memory } => todo!(), - Operator::I32Load16S { memory } => todo!(), - Operator::I32Load16U { memory } => todo!(), - Operator::I64Load8S { memory } => todo!(), - Operator::I64Load8U { memory } => todo!(), - Operator::I64Load16S { memory } => todo!(), - Operator::I64Load16U { memory } => todo!(), - Operator::I64Load32S { memory } => todo!(), - Operator::I64Load32U { memory } => todo!(), + Operator::I32Load { memory } => binaryen::Expression::load( + into_mod, + 4, + false, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::I64Load { memory } => binaryen::Expression::load( + into_mod, + 8, + false, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::F32Load { memory } => binaryen::Expression::load( + into_mod, + 4, + false, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::F64Load { memory } => binaryen::Expression::load( + into_mod, + 8, + false, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::I32Load8S { memory } => binaryen::Expression::load( + into_mod, + 1, + true, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::I32Load8U { memory } => binaryen::Expression::load( + into_mod, + 1, + false, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::I32Load16S { memory } => binaryen::Expression::load( + into_mod, + 2, + true, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::I32Load16U { memory } => binaryen::Expression::load( + into_mod, + 2, + false, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::I64Load8S { memory } => binaryen::Expression::load( + into_mod, + 1, + true, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::I64Load8U { memory } => binaryen::Expression::load( + into_mod, + 1, + false, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::I64Load16S { memory } => binaryen::Expression::load( + into_mod, + 2, + true, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::I64Load16U { memory } => binaryen::Expression::load( + into_mod, + 2, + false, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::I64Load32S { memory } => binaryen::Expression::load( + into_mod, + 4, + true, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), + Operator::I64Load32U { memory } => binaryen::Expression::load( + into_mod, + 4, + false, + memory.offset, + memory.align, + tys[0], + args[0], + memory.memory, + ), - Operator::I32Store { memory } => todo!(), - Operator::I64Store { memory } => todo!(), - Operator::F32Store { memory } => todo!(), - Operator::F64Store { memory } => todo!(), - Operator::I32Store8 { memory } => todo!(), - Operator::I32Store16 { memory } => todo!(), - Operator::I64Store8 { memory } => todo!(), - Operator::I64Store16 { memory } => todo!(), - Operator::I64Store32 { memory } => todo!(), + Operator::I32Store { memory } => binaryen::Expression::store( + into_mod, + 4, + memory.offset, + memory.align, + Type::I32, + args[0], + args[1], + memory.memory, + ), + Operator::I64Store { memory } => binaryen::Expression::store( + into_mod, + 8, + memory.offset, + memory.align, + Type::I64, + args[0], + args[1], + memory.memory, + ), + Operator::F32Store { memory } => binaryen::Expression::store( + into_mod, + 4, + memory.offset, + memory.align, + Type::F32, + args[0], + args[1], + memory.memory, + ), + Operator::F64Store { memory } => binaryen::Expression::store( + into_mod, + 8, + memory.offset, + memory.align, + Type::F64, + args[0], + args[1], + memory.memory, + ), + Operator::I32Store8 { memory } => binaryen::Expression::store( + into_mod, + 1, + memory.offset, + memory.align, + Type::I32, + args[0], + args[1], + memory.memory, + ), + Operator::I32Store16 { memory } => binaryen::Expression::store( + into_mod, + 2, + memory.offset, + memory.align, + Type::I32, + args[0], + args[1], + memory.memory, + ), + Operator::I64Store8 { memory } => binaryen::Expression::store( + into_mod, + 1, + memory.offset, + memory.align, + Type::I64, + args[0], + args[1], + memory.memory, + ), + Operator::I64Store16 { memory } => binaryen::Expression::store( + into_mod, + 2, + memory.offset, + memory.align, + Type::I64, + args[0], + args[1], + memory.memory, + ), + Operator::I64Store32 { memory } => binaryen::Expression::store( + into_mod, + 4, + memory.offset, + memory.align, + Type::I64, + args[0], + args[1], + memory.memory, + ), - Operator::I32Const { value } => todo!(), - Operator::I64Const { value } => todo!(), - Operator::F32Const { value } => todo!(), - Operator::F64Const { value } => todo!(), + Operator::I32Const { value } => binaryen::Expression::const_i32(into_mod, value), + Operator::I64Const { value } => binaryen::Expression::const_i64(into_mod, value), + Operator::F32Const { value } => binaryen::Expression::const_f32(into_mod, value), + Operator::F64Const { value } => binaryen::Expression::const_f64(into_mod, value), Operator::I32Eqz => todo!(), Operator::I32Eq => todo!(), diff --git a/src/lib.rs b/src/lib.rs index 8078dd8..66e486e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,4 +16,4 @@ pub mod passes; mod scoped_map; pub use ir::*; -pub use ops::Operator; +pub use ops::{Ieee32, Ieee64, Operator}; diff --git a/src/ops.rs b/src/ops.rs index e6279ff..1da5250 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -1,13 +1,14 @@ //! Operators. -use wasmparser::{Ieee32, Ieee64, MemoryImmediate}; - use crate::{Func, Global, Local, Memory, Signature, Table, Type}; +use std::convert::TryFrom; +use wasmparser::MemoryImmediate; +pub use wasmparser::{Ieee32, Ieee64}; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct MemoryArg { - pub align: u8, - pub offset: u64, + pub align: u32, + pub offset: u32, pub memory: Memory, } @@ -334,7 +335,9 @@ impl<'a, 'b> std::convert::TryFrom<&'b wasmparser::Operator<'a>> for Operator { local_index: Local::from(local_index), }), &wasmparser::Operator::Select => Ok(Operator::Select), - &wasmparser::Operator::TypedSelect { ty } => Ok(Operator::TypedSelect { ty: ty.into() }), + &wasmparser::Operator::TypedSelect { ty } => { + Ok(Operator::TypedSelect { ty: ty.into() }) + } &wasmparser::Operator::GlobalGet { global_index } => Ok(Operator::GlobalGet { global_index: Global::from(global_index), }), @@ -576,8 +579,8 @@ impl<'a, 'b> std::convert::TryFrom<&'b wasmparser::Operator<'a>> for Operator { impl std::convert::From for MemoryArg { fn from(value: MemoryImmediate) -> MemoryArg { MemoryArg { - align: value.align, - offset: value.offset, + align: value.align as u32, + offset: u32::try_from(value.offset).expect("offset too large"), memory: Memory::from(value.memory), } }