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

Implement vector-of-vector comparison in move-native. #226

Merged
merged 1 commit into from
Jul 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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();
}
}