Skip to content
This repository has been archived by the owner on Mar 20, 2024. It is now read-only.

Commit

Permalink
Implement vector-of-vector comparison in move-native. (#226)
Browse files Browse the repository at this point in the history
This patch extends the baseline `move-native` `vec_cmp_eq` routine
to handle vector<vector<T>>.

Uncomment `test_vec_vec_bool` in the stdlib-bcs serializer test
(which now passes).

Add more tests to vec.move to exercise vec_cmp_eq with vec-of-vec.
  • Loading branch information
nvjle committed Jul 9, 2023
1 parent bb56b26 commit af5ebfc
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 9 deletions.
18 changes: 17 additions & 1 deletion language/move-native/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -688,7 +688,21 @@ mod rt {
let mut rv2 = borrow_move_vec_as_rust_vec::<MoveAddress>(v2);
rv1.deref().eq(rv2.deref())
}
_ => todo!()
TypeDesc::Vector => {
assert!(v1_len == v2_len, "unexpected vec cmp lengths");
let inner_element_type = *(*type_ve.type_info).vector.element_type;
let mut partial_eq_result = true;
for i in 0..v1_len {
let anyval_ref1 = V::borrow(type_ve, v1, i);
let anyval_ref2 = V::borrow(type_ve, v2, i);
let mv_ut_vec1 = &*(anyval_ref1 as *const AnyValue as *const MoveUntypedVector);
let mv_ut_vec2 = &*(anyval_ref2 as *const AnyValue as *const MoveUntypedVector);
let tb = vec_cmp_eq(&inner_element_type, mv_ut_vec1, mv_ut_vec2);
partial_eq_result &= tb;
}
partial_eq_result
}
_ => todo!("vec_cmp_eq: unhandled element type: {:?}", type_ve.type_desc)
};
is_eq
}
Expand Down Expand Up @@ -2031,13 +2045,15 @@ pub(crate) mod target_defs {

mod globals {
use alloc::alloc::{GlobalAlloc, Layout};
use alloc::format;
use core::mem::size_of;
use core::ptr::null_mut;

const PANIC_ABORT_CODE: u64 = 101;

#[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! {
super::print_string(&format!("{}", info));
super::abort(PANIC_ABORT_CODE);
}

Expand Down
20 changes: 14 additions & 6 deletions language/tools/move-mv-llvm-compiler/src/stackless/translate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1516,20 +1516,28 @@ impl<'mm, 'up> FunctionContext<'mm, 'up> {
mty::Type::Vector(ety) => &**ety,
_ => unreachable!(),
};
assert!(
vec_elt_cmp_mty.is_number()
|| vec_elt_cmp_mty.is_bool()
|| vec_elt_cmp_mty.is_address()
);
assert!(
pred == llvm::LLVMIntPredicate::LLVMIntEQ || pred == llvm::LLVMIntPredicate::LLVMIntNE
);

let dst_reg = self.emit_rtcall_with_retval(RtCall::VecCmpEq(
let mut dst_reg = self.emit_rtcall_with_retval(RtCall::VecCmpEq(
self.locals[src[0]].llval.as_any_value(),
self.locals[src[1]].llval.as_any_value(),
vec_elt_cmp_mty.clone(),
));

// The above produces equality, so invert if this is a not-equal comparison.
if pred == llvm::LLVMIntPredicate::LLVMIntNE {
let cval =
llvm::Constant::int(self.module_cx.llvm_cx.int_type(1), U256::one()).as_any_value();
dst_reg = self.module_cx.llvm_builder.build_binop(
llvm_sys::LLVMOpcode::LLVMXor,
dst_reg,
cval,
"",
);
}

self.store_reg(dst[0], dst_reg);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ module 0x10::tests {
};
let vs: vector<u8> = bcs::to_bytes(&v);
let vv: vector<vector<bool>> = bcs::test_from_bytes(&vs);
//assert!(v == vv, 11); // fixme internal compiler error
assert!(v == vv, 11);
}

struct TestVecStruct has drop {
Expand Down Expand Up @@ -223,7 +223,7 @@ script {
tests::test_vec_u256();
tests::test_vec_address();
//tests::test_vec_signer(); // fixme
//tests::test_vec_vec_bool(); // fixme
tests::test_vec_vec_bool();
//tests::test_vec_struct(); // fixme
}
}
108 changes: 108 additions & 0 deletions language/tools/move-mv-llvm-compiler/tests/rbpf-tests/vec.move
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,112 @@ module 0x10::tests {

vector::destroy_empty(v);
}

// Test vector<vector<u32>>.
public fun test_vec_vec_u32() {
// Inner vector<u32> a.
let vai1: vector<u32> = vector::empty();
vector::push_back(&mut vai1, 8086);
vector::push_back(&mut vai1, 8087);
vector::push_back(&mut vai1, 8088);
let vai2: vector<u32> = vector::empty();
vector::push_back(&mut vai2, 1);
vector::push_back(&mut vai2, 2);
vector::push_back(&mut vai2, 3);

// Inner vector<u32> b.
let vbi1: vector<u32> = vector::empty();
vector::push_back(&mut vbi1, 8086);
vector::push_back(&mut vbi1, 8087);
vector::push_back(&mut vbi1, 8088);
let vbi2: vector<u32> = vector::empty();
vector::push_back(&mut vbi2, 1);
vector::push_back(&mut vbi2, 2);
vector::push_back(&mut vbi2, 3);

// Outer vector<vector<u32>> a.
let vao: vector<vector<u32>> = vector::empty();
vector::push_back(&mut vao, vai1);
vector::push_back(&mut vao, vai2);

// Outer vector<vector<u32>> b.
let vbo: vector<vector<u32>> = vector::empty();
vector::push_back(&mut vbo, vbi1);
vector::push_back(&mut vbo, vbi2);

assert!(vao == vbo, 20);

// Inner vector<u32> c.
let vci1: vector<u32> = vector::empty();
vector::push_back(&mut vci1, 500);

// Inner vector<u32> d.
let vdi1: vector<u32> = vector::empty();
vector::push_back(&mut vdi1, 600);

// Outer vector<vector<u32>> a2.
let va2o: vector<vector<u32>> = vector::empty();
vector::push_back(&mut va2o, vci1);

// Outer vector<vector<u32>> b2.
let vb2o: vector<vector<u32>> = vector::empty();
vector::push_back(&mut vb2o, vdi1);

assert!(va2o != vb2o, 21);
}

// Test vector<vector<bool>>.
public fun test_vec_vec_bool() {
// Inner vector<bool> a.
let vai1: vector<bool> = vector::empty();
vector::push_back(&mut vai1, true);
vector::push_back(&mut vai1, false);
vector::push_back(&mut vai1, true);
let vai2: vector<bool> = vector::empty();
vector::push_back(&mut vai2, true);
vector::push_back(&mut vai2, true);
vector::push_back(&mut vai2, false);

// Inner vector<bool> b.
let vbi1: vector<bool> = vector::empty();
vector::push_back(&mut vbi1, true);
vector::push_back(&mut vbi1, false);
vector::push_back(&mut vbi1, true);
let vbi2: vector<bool> = vector::empty();
vector::push_back(&mut vbi2, true);
vector::push_back(&mut vbi2, true);
vector::push_back(&mut vbi2, false);

// Outer vector<vector<bool>> a.
let vao: vector<vector<bool>> = vector::empty();
vector::push_back(&mut vao, vai1);
vector::push_back(&mut vao, vai2);

// Outer vector<vector<bool>> b.
let vbo: vector<vector<bool>> = vector::empty();
vector::push_back(&mut vbo, vbi1);
vector::push_back(&mut vbo, vbi2);

assert!(vao == vbo, 30);

// Inner vector<bool> c.
let vci1: vector<bool> = vector::empty();
vector::push_back(&mut vci1, false);

// Inner vector<bool> d.
let vdi1: vector<bool> = vector::empty();
vector::push_back(&mut vdi1, true);

// Outer vector<vector<bool>> a2.
let va2o: vector<vector<bool>> = vector::empty();
vector::push_back(&mut va2o, vci1);

// Outer vector<vector<bool>> b2.
let vb2o: vector<vector<bool>> = vector::empty();
vector::push_back(&mut vb2o, vdi1);

assert!(va2o != vb2o, 31);
}
}

script {
Expand All @@ -214,5 +320,7 @@ script {
tests::test_u128();
tests::test_u256();
tests::test_address();
tests::test_vec_vec_u32();
tests::test_vec_vec_bool();
}
}

0 comments on commit af5ebfc

Please sign in to comment.