@ -825,16 +825,6 @@ impl Compiler<'_, '_> {
let cur_src_ptr = self . gen_local ( src_opts . ptr ( ) ) ;
let cur_src_ptr = self . gen_local ( src_opts . ptr ( ) ) ;
let remaining = self . gen_local ( src_opts . ptr ( ) ) ;
let remaining = self . gen_local ( src_opts . ptr ( ) ) ;
let iconst = | i : i32 , ty : ValType | match ty {
ValType ::I32 = > I32Const ( i32 ::try_from ( i ) . unwrap ( ) ) ,
ValType ::I64 = > I64Const ( i64 ::try_from ( i ) . unwrap ( ) ) ,
_ = > unreachable ! ( ) ,
} ;
let src_add = if src_opts . memory64 { I64Add } else { I32Add } ;
let dst_add = if dst_opts . memory64 { I64Add } else { I32Add } ;
let src_eqz = if src_opts . memory64 { I64Eqz } else { I32Eqz } ;
let src_ne = if src_opts . memory64 { I64Ne } else { I32Ne } ;
// This block encompasses the entire loop and is use to exit before even
// This block encompasses the entire loop and is use to exit before even
// entering the loop if the list size is zero.
// entering the loop if the list size is zero.
self . instruction ( Block ( BlockType ::Empty ) ) ;
self . instruction ( Block ( BlockType ::Empty ) ) ;
@ -842,7 +832,7 @@ impl Compiler<'_, '_> {
// Set the `remaining` local and only continue if it's > 0
// Set the `remaining` local and only continue if it's > 0
self . instruction ( LocalGet ( src_len ) ) ;
self . instruction ( LocalGet ( src_len ) ) ;
self . instruction ( LocalTee ( remaining ) ) ;
self . instruction ( LocalTee ( remaining ) ) ;
self . instruction ( src_eqz . clone ( ) ) ;
self . ptr_eqz ( src_opts ) ;
self . instruction ( BrIf ( 0 ) ) ;
self . instruction ( BrIf ( 0 ) ) ;
// Initialize the two destination pointers to their initial values
// Initialize the two destination pointers to their initial values
@ -868,29 +858,25 @@ impl Compiler<'_, '_> {
// Update the two loop pointers
// Update the two loop pointers
if src_size > 0 {
if src_size > 0 {
let src_size = i32 ::try_from ( src_size ) . unwrap ( ) ;
self . instruction ( LocalGet ( cur_src_ptr ) ) ;
self . instruction ( LocalGet ( cur_src_ptr ) ) ;
self . instruction ( iconst ( src_size , src_opts . ptr ( ) ) ) ;
self . ptr_uconst ( src_opts , u32 ::try_from ( src_size ) . unwrap ( ) ) ;
self . instruction ( src_add . clone ( ) ) ;
self . ptr_add ( src_opts ) ;
self . instruction ( LocalSet ( cur_src_ptr ) ) ;
self . instruction ( LocalSet ( cur_src_ptr ) ) ;
}
}
if dst_size > 0 {
if dst_size > 0 {
let dst_size = i32 ::try_from ( dst_size ) . unwrap ( ) ;
self . instruction ( LocalGet ( cur_dst_ptr ) ) ;
self . instruction ( LocalGet ( cur_dst_ptr ) ) ;
self . instruction ( iconst ( dst_size , dst_opts . ptr ( ) ) ) ;
self . ptr_uconst ( dst_opts , u32 ::try_from ( dst_size ) . unwrap ( ) ) ;
self . instruction ( dst_add . clone ( ) ) ;
self . ptr_add ( dst_opts ) ;
self . instruction ( LocalSet ( cur_dst_ptr ) ) ;
self . instruction ( LocalSet ( cur_dst_ptr ) ) ;
}
}
// Update the remaining count, falling through to break out if it's zero
// Update the remaining count, falling through to break out if it's zero
// now.
// now.
self . instruction ( LocalGet ( remaining ) ) ;
self . instruction ( LocalGet ( remaining ) ) ;
self . instruction ( iconst ( - 1 , src_opts . ptr ( ) ) ) ;
self . ptr_iconst ( src_opts , - 1 ) ;
self . instruction ( src_add . clone ( ) ) ;
self . ptr_add ( src_opts ) ;
self . instruction ( LocalTee ( remaining ) ) ;
self . instruction ( LocalTee ( remaining ) ) ;
self . instruction ( iconst ( 0 , src_opts . ptr ( ) ) ) ;
self . ptr_br_if ( src_opts , 0 ) ;
self . instruction ( src_ne . clone ( ) ) ;
self . instruction ( BrIf ( 0 ) ) ;
self . instruction ( End ) ; // end of loop
self . instruction ( End ) ; // end of loop
self . instruction ( End ) ; // end of block
self . instruction ( End ) ; // end of block
}
}
@ -1489,18 +1475,9 @@ impl Compiler<'_, '_> {
}
}
self . instruction ( LocalGet ( memory . addr_local ) ) ;
self . instruction ( LocalGet ( memory . addr_local ) ) ;
assert ! ( align . is_power_of_two ( ) ) ;
assert ! ( align . is_power_of_two ( ) ) ;
if memory . opts . memory64 {
self . ptr_uconst ( memory . opts , u32 ::try_from ( align - 1 ) . unwrap ( ) ) ;
let mask = i64 ::try_from ( align - 1 ) . unwrap ( ) ;
self . ptr_and ( memory . opts ) ;
self . instruction ( I64Const ( mask ) ) ;
self . ptr_if ( memory . opts , BlockType ::Empty ) ;
self . instruction ( I64And ) ;
self . instruction ( I64Const ( 0 ) ) ;
self . instruction ( I64Ne ) ;
} else {
let mask = i32 ::try_from ( align - 1 ) . unwrap ( ) ;
self . instruction ( I32Const ( mask ) ) ;
self . instruction ( I32And ) ;
}
self . instruction ( If ( BlockType ::Empty ) ) ;
self . trap ( Trap ::UnalignedPointer ) ;
self . trap ( Trap ::UnalignedPointer ) ;
self . instruction ( End ) ;
self . instruction ( End ) ;
}
}
@ -1515,22 +1492,11 @@ impl Compiler<'_, '_> {
}
}
assert ! ( align . is_power_of_two ( ) ) ;
assert ! ( align . is_power_of_two ( ) ) ;
self . instruction ( LocalGet ( mem . addr_local ) ) ;
self . instruction ( LocalGet ( mem . addr_local ) ) ;
if mem . opts . memory64 {
self . ptr_uconst ( mem . opts , mem . offset ) ;
self . instruction ( I64Const ( i64 ::from ( mem . offset ) ) ) ;
self . ptr_add ( mem . opts ) ;
self . instruction ( I64Add ) ;
self . ptr_uconst ( mem . opts , u32 ::try_from ( align - 1 ) . unwrap ( ) ) ;
let mask = i64 ::try_from ( align - 1 ) . unwrap ( ) ;
self . ptr_and ( mem . opts ) ;
self . instruction ( I64Const ( mask ) ) ;
self . ptr_if ( mem . opts , BlockType ::Empty ) ;
self . instruction ( I64And ) ;
self . instruction ( I64Const ( 0 ) ) ;
self . instruction ( I64Ne ) ;
} else {
self . instruction ( I32Const ( mem . i32_offset ( ) ) ) ;
self . instruction ( I32Add ) ;
let mask = i32 ::try_from ( align - 1 ) . unwrap ( ) ;
self . instruction ( I32Const ( mask ) ) ;
self . instruction ( I32And ) ;
}
self . instruction ( If ( BlockType ::Empty ) ) ;
self . trap ( Trap ::AssertFailed ( "pointer not aligned" ) ) ;
self . trap ( Trap ::AssertFailed ( "pointer not aligned" ) ) ;
self . instruction ( End ) ;
self . instruction ( End ) ;
}
}
@ -1538,22 +1504,12 @@ impl Compiler<'_, '_> {
fn malloc < 'a > ( & mut self , opts : & 'a Options , size : MallocSize , align : usize ) -> Memory < 'a > {
fn malloc < 'a > ( & mut self , opts : & 'a Options , size : MallocSize , align : usize ) -> Memory < 'a > {
let addr_local = self . gen_local ( opts . ptr ( ) ) ;
let addr_local = self . gen_local ( opts . ptr ( ) ) ;
let realloc = opts . realloc . unwrap ( ) ;
let realloc = opts . realloc . unwrap ( ) ;
if opts . memory64 {
self . ptr_uconst ( opts , 0 ) ;
self . instruction ( I64Const ( 0 ) ) ;
self . ptr_uconst ( opts , 0 ) ;
self . instruction ( I64Const ( 0 ) ) ;
self . ptr_uconst ( opts , u32 ::try_from ( align ) . unwrap ( ) ) ;
self . instruction ( I64Const ( i64 ::try_from ( align ) . unwrap ( ) ) ) ;
match size {
match size {
MallocSize ::Const ( size ) = > self . ptr_uconst ( opts , u32 ::try_from ( size ) . unwrap ( ) ) ,
MallocSize ::Const ( size ) = > self . instruction ( I64Const ( i64 ::try_from ( size ) . unwrap ( ) ) ) ,
MallocSize ::Local ( idx ) = > self . instruction ( LocalGet ( idx ) ) ,
MallocSize ::Local ( idx ) = > self . instruction ( LocalGet ( idx ) ) ,
}
} else {
self . instruction ( I32Const ( 0 ) ) ;
self . instruction ( I32Const ( 0 ) ) ;
self . instruction ( I32Const ( i32 ::try_from ( align ) . unwrap ( ) ) ) ;
match size {
MallocSize ::Const ( size ) = > self . instruction ( I32Const ( i32 ::try_from ( size ) . unwrap ( ) ) ) ,
MallocSize ::Local ( idx ) = > self . instruction ( LocalGet ( idx ) ) ,
}
}
}
self . instruction ( Call ( realloc . as_u32 ( ) ) ) ;
self . instruction ( Call ( realloc . as_u32 ( ) ) ) ;
self . instruction ( LocalSet ( addr_local ) ) ;
self . instruction ( LocalSet ( addr_local ) ) ;
@ -1747,6 +1703,62 @@ impl Compiler<'_, '_> {
}
}
}
}
fn ptr_add ( & mut self , opts : & Options ) {
if opts . memory64 {
self . instruction ( I64Add ) ;
} else {
self . instruction ( I32Add ) ;
}
}
fn ptr_eqz ( & mut self , opts : & Options ) {
if opts . memory64 {
self . instruction ( I64Eqz ) ;
} else {
self . instruction ( I32Eqz ) ;
}
}
fn ptr_uconst ( & mut self , opts : & Options , val : u32 ) {
if opts . memory64 {
self . instruction ( I64Const ( val . into ( ) ) ) ;
} else {
self . instruction ( I32Const ( val as i32 ) ) ;
}
}
fn ptr_iconst ( & mut self , opts : & Options , val : i32 ) {
if opts . memory64 {
self . instruction ( I64Const ( val . into ( ) ) ) ;
} else {
self . instruction ( I32Const ( val ) ) ;
}
}
fn ptr_and ( & mut self , opts : & Options ) {
if opts . memory64 {
self . instruction ( I64And ) ;
} else {
self . instruction ( I32And ) ;
}
}
fn ptr_if ( & mut self , opts : & Options , ty : BlockType ) {
if opts . memory64 {
self . instruction ( I64Const ( 0 ) ) ;
self . instruction ( I64Ne ) ;
}
self . instruction ( If ( ty ) ) ;
}
fn ptr_br_if ( & mut self , opts : & Options , depth : u32 ) {
if opts . memory64 {
self . instruction ( I64Const ( 0 ) ) ;
self . instruction ( I64Ne ) ;
}
self . instruction ( BrIf ( depth ) ) ;
}
fn f32_load ( & mut self , mem : & Memory ) {
fn f32_load ( & mut self , mem : & Memory ) {
self . instruction ( LocalGet ( mem . addr_local ) ) ;
self . instruction ( LocalGet ( mem . addr_local ) ) ;
self . instruction ( F32Load ( mem . memarg ( 2 ) ) ) ;
self . instruction ( F32Load ( mem . memarg ( 2 ) ) ) ;
@ -1925,10 +1937,6 @@ fn payload_offset<'a>(
}
}
impl < 'a > Memory < 'a > {
impl < 'a > Memory < 'a > {
fn i32_offset ( & self ) -> i32 {
self . offset as i32
}
fn memarg ( & self , align : u32 ) -> MemArg {
fn memarg ( & self , align : u32 ) -> MemArg {
MemArg {
MemArg {
offset : u64 ::from ( self . offset ) ,
offset : u64 ::from ( self . offset ) ,