Add unit test suites (#3490)

This commit is contained in:
Zhang, Yi
2024-06-04 11:24:27 +08:00
committed by GitHub
parent 0a80cc4e94
commit 380cd7b0e7
194 changed files with 14104 additions and 34 deletions

View File

@ -0,0 +1,67 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
cmake_minimum_required(VERSION 3.14)
project(test-memory64)
add_definitions(-DRUN_ON_LINUX)
set(WAMR_BUILD_LIBC_WASI 1)
set(WAMR_BUILD_APP_FRAMEWORK 0)
# TODO: Currently only support classic interpreter mode
set(WAMR_BUILD_AOT 0)
set(WAMR_BUILD_INTERP 1)
set(WAMR_BUILD_FAST_INTERP 0)
set(WAMR_BUILD_JIT 0)
set(WAMR_BUILD_FAST_JIT 0)
set(WAMR_BUILD_MEMORY64 1)
set(WAMR_BUILD_SHARED_MEMORY 1)
# if only load this CMake other than load it as subdirectory
# include(GoogleTest)
include(../unit_common.cmake)
set(LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
if (NOT EXISTS "${LLVM_SRC_ROOT}/build")
message(FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build")
endif ()
set(CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}")
find_package(LLVM REQUIRED CONFIG)
include_directories(${LLVM_INCLUDE_DIRS})
add_definitions(${LLVM_DEFINITIONS})
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
include(${IWASM_DIR}/compilation/iwasm_compl.cmake)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
file(GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
set(UNIT_SOURCE ${source_all})
aux_source_directory(. SRC_LIST)
set(unit_test_sources
${UNIT_SOURCE}
${WAMR_RUNTIME_LIB_SOURCE}
${UNCOMMON_SHARED_SOURCE}
${SRC_LIST}
)
# Now simply link against gtest or gtest_main as needed. Eg
add_executable(memory64_test ${unit_test_sources})
target_link_libraries(memory64_test ${LLVM_AVAILABLE_LIBS} gtest_main)
add_custom_command(TARGET memory64_test POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps/*.wasm
${CMAKE_CURRENT_BINARY_DIR}/
COMMENT "Copy test wasm files to the directory of google test"
)
gtest_discover_tests(memory64_test)

View File

@ -0,0 +1,355 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "memory64_common.h"
// To use a test fixture and Value Parameterized Tests,
// derive a class from testing::TestWithParam.
class memory64_atomic_test_suite : public testing::TestWithParam<RunningMode>
{
protected:
bool load_wasm_file(const char *wasm_file)
{
const char *file;
unsigned char *wasm_file_buf;
uint32 wasm_file_size;
file = wasm_file;
wasm_file_buf =
(unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size);
if (!wasm_file_buf)
goto fail;
if (!(module = wasm_runtime_load(wasm_file_buf, wasm_file_size,
error_buf, sizeof(error_buf)))) {
printf("Load wasm module failed. error: %s\n", error_buf);
goto fail;
}
return true;
fail:
if (!module)
wasm_runtime_unload(module);
return false;
}
bool init_exec_env()
{
if (!(module_inst =
wasm_runtime_instantiate(module, stack_size, heap_size,
error_buf, sizeof(error_buf)))) {
printf("Instantiate wasm module failed. error: %s\n", error_buf);
goto fail;
}
if (!(exec_env =
wasm_runtime_create_exec_env(module_inst, stack_size))) {
printf("Create wasm execution environment failed.\n");
goto fail;
}
return true;
fail:
if (exec_env)
wasm_runtime_destroy_exec_env(exec_env);
if (module_inst)
wasm_runtime_unload(module);
return false;
}
void destory_exec_env()
{
wasm_runtime_destroy_exec_env(exec_env);
wasm_runtime_deinstantiate(module_inst);
wasm_runtime_unload(module);
}
public:
// If your test fixture defines SetUpTestSuite() or TearDownTestSuite()
// they must be declared public rather than protected in order to use
// TEST_P.
// virtual void SetUp() will be called before each test is run. You
// should define it if you need to initialize the variables.
// Otherwise, this can be skipped.
virtual void SetUp()
{
memset(&init_args, 0, sizeof(RuntimeInitArgs));
init_args.mem_alloc_type = Alloc_With_Pool;
init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
ASSERT_EQ(wasm_runtime_full_init(&init_args), true);
ASSERT_TRUE(load_wasm_file("atomic_opcodes.wasm"));
ASSERT_TRUE(init_exec_env());
running_mode = GetParam();
ASSERT_TRUE(wasm_runtime_set_running_mode(module_inst, running_mode));
ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst));
for (auto &iter : func_map) {
iter.second =
wasm_runtime_lookup_function(module_inst, iter.first.c_str());
ASSERT_TRUE(iter.second != NULL);
}
cleanup = true;
}
static void SetUpTestCase() {}
// virtual void TearDown() will be called after each test is run.
// You should define it if there is cleanup work to do. Otherwise,
// you don't have to provide it.
//
virtual void TearDown()
{
if (cleanup) {
destory_exec_env();
wasm_runtime_destroy();
cleanup = false;
}
}
static void TearDownTestCase() {}
RuntimeInitArgs init_args;
wasm_module_t module = NULL;
wasm_module_inst_t module_inst = NULL;
wasm_exec_env_t exec_env = NULL;
RunningMode running_mode;
char error_buf[128];
char global_heap_buf[512 * 1024];
uint32_t stack_size = 8092, heap_size = 8092;
bool cleanup = true;
std::unordered_map<std::string, wasm_function_inst_t> func_map = {
{ "i32_atomic_store", nullptr },
{ "i32_atomic_store8", nullptr },
{ "i32_atomic_store16", nullptr },
{ "i64_atomic_store", nullptr },
{ "i64_atomic_store8", nullptr },
{ "i64_atomic_store16", nullptr },
{ "i64_atomic_store32", nullptr },
{ "i32_atomic_load", nullptr },
{ "i32_atomic_load8_u", nullptr },
{ "i32_atomic_load16_u", nullptr },
{ "i64_atomic_load", nullptr },
{ "i64_atomic_load8_u", nullptr },
{ "i64_atomic_load16_u", nullptr },
{ "i64_atomic_load32_u", nullptr },
{ "i32_atomic_rmw_add", nullptr },
{ "i32_atomic_rmw8_add_u", nullptr },
{ "i32_atomic_rmw16_add_u", nullptr },
{ "i64_atomic_rmw_add", nullptr },
{ "i64_atomic_rmw8_add_u", nullptr },
{ "i64_atomic_rmw16_add_u", nullptr },
{ "i64_atomic_rmw32_add_u", nullptr },
{ "i64_atomic_rmw_cmpxchg", nullptr },
};
uint32_t wasm_argv[6], i32;
uint64_t i64;
};
TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_st)
{
// store at 0x2000, with value 0xbeefdead
PUT_I64_TO_ADDR(wasm_argv, 0x2000);
PUT_I64_TO_ADDR(wasm_argv + 2, 0xcafedeadbeefdead);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store"],
4, wasm_argv));
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2,
wasm_argv));
// check return value: 0xcafedeadbeefdead:i64
i64 = 0xcafedeadbeefdead;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
// store at 0x2000, with value 0xbeefbeef
PUT_I64_TO_ADDR(wasm_argv, 0x2000);
PUT_I64_TO_ADDR(wasm_argv + 2, 0xdeadbeef);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store32"],
4, wasm_argv));
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2,
wasm_argv));
// check return value: 0xcafedeaddeadbeef:i64
i64 = 0xcafedeaddeadbeef;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
// store at 0x2000, with value 0xcafe
PUT_I64_TO_ADDR(wasm_argv, 0x2000);
PUT_I64_TO_ADDR(wasm_argv + 2, 0xcafe);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store16"],
4, wasm_argv));
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2,
wasm_argv));
// check return value: 0xcafedeaddeadcafe:i64
i64 = 0xcafedeaddeadcafe;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
// store at 0x2000, with value 0xcafe
PUT_I64_TO_ADDR(wasm_argv, 0x2000);
PUT_I64_TO_ADDR(wasm_argv + 2, 0xaa);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_store8"],
4, wasm_argv));
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2,
wasm_argv));
// check return value: 0xcafedeaddeadcaaa:i64
i64 = 0xcafedeaddeadcaaa;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
}
TEST_P(memory64_atomic_test_suite, atomic_opcodes_i32_st)
{
// store at 0x1000, with value 0xbeefbeef
PUT_I64_TO_ADDR(wasm_argv, 0x2000);
PUT_I64_TO_ADDR(wasm_argv + 2, 0xaabbccdd);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_store"],
4, wasm_argv));
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2,
wasm_argv));
// check return value: 0xaabbccdd:i32
i32 = 0xaabbccdd;
ASSERT_EQ(i32, wasm_argv[0]);
// store at 0x1000, with value 0xcafe
PUT_I64_TO_ADDR(wasm_argv, 0x2000);
PUT_I64_TO_ADDR(wasm_argv + 2, 0xcafe);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_store16"],
4, wasm_argv));
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2,
wasm_argv));
// check return value: 0xaabbcafe:i32
i32 = 0xaabbcafe;
ASSERT_EQ(i32, wasm_argv[0]);
PUT_I64_TO_ADDR(wasm_argv, 0x2000);
PUT_I64_TO_ADDR(wasm_argv + 2, 0xaa);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_store8"],
4, wasm_argv));
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2,
wasm_argv));
// check return value: 0xaabbcaaa:i32
i32 = 0xaabbcaaa;
ASSERT_EQ(i32, wasm_argv[0]);
}
TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_ld)
{
// from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10
PUT_I64_TO_ADDR(wasm_argv, 0x0);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2,
wasm_argv));
// check return value: 0x0807060504030201:i64
i64 = 0x0807060504030201;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
PUT_I64_TO_ADDR(wasm_argv, 0x8);
ASSERT_TRUE(wasm_runtime_call_wasm(
exec_env, func_map["i64_atomic_load32_u"], 2, wasm_argv));
// check return value: 0x0C0B0A09:i64
i64 = 0x0C0B0A09;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
PUT_I64_TO_ADDR(wasm_argv, 0x8);
ASSERT_TRUE(wasm_runtime_call_wasm(
exec_env, func_map["i64_atomic_load16_u"], 2, wasm_argv));
// check return value: 0x0A09:i64
i64 = 0x0A09;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
PUT_I64_TO_ADDR(wasm_argv, 0x0A);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load8_u"],
2, wasm_argv));
// check return value: 0x0B:i64
i64 = 0x0B;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
}
TEST_P(memory64_atomic_test_suite, atomic_opcodes_i32_ld)
{
// from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10
PUT_I64_TO_ADDR(wasm_argv, 0x0);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load"], 2,
wasm_argv));
// check return value: 0x04030201:i32
i32 = 0x04030201;
ASSERT_EQ(i32, wasm_argv[0]);
PUT_I64_TO_ADDR(wasm_argv, 0x8);
ASSERT_TRUE(wasm_runtime_call_wasm(
exec_env, func_map["i32_atomic_load16_u"], 2, wasm_argv));
// check return value: 0x0A09:i32
i32 = 0x0A09;
ASSERT_EQ(i32, wasm_argv[0]);
PUT_I64_TO_ADDR(wasm_argv, 0xA);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i32_atomic_load8_u"],
2, wasm_argv));
// check return value: 0x0B:i32
i32 = 0x0B;
ASSERT_EQ(i32, wasm_argv[0]);
}
TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_rmw_add)
{
// from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10
PUT_I64_TO_ADDR(wasm_argv, 0x8);
PUT_I64_TO_ADDR(wasm_argv + 2, 0x1010101020202020);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_rmw_add"],
4, wasm_argv));
i64 = 0x100F0E0D0C0B0A09;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
PUT_I64_TO_ADDR(wasm_argv, 0x8);
PUT_I64_TO_ADDR(wasm_argv + 2, 0x10103030);
ASSERT_TRUE(wasm_runtime_call_wasm(
exec_env, func_map["i64_atomic_rmw32_add_u"], 4, wasm_argv));
i64 = 0x2C2B2A29;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
PUT_I64_TO_ADDR(wasm_argv, 0x8);
PUT_I64_TO_ADDR(wasm_argv + 2, 0x1020);
ASSERT_TRUE(wasm_runtime_call_wasm(
exec_env, func_map["i64_atomic_rmw16_add_u"], 4, wasm_argv));
i64 = 0x5A59;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
PUT_I64_TO_ADDR(wasm_argv, 0x8);
PUT_I64_TO_ADDR(wasm_argv + 2, 0x30);
ASSERT_TRUE(wasm_runtime_call_wasm(
exec_env, func_map["i64_atomic_rmw8_add_u"], 4, wasm_argv));
i64 = 0x79;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
PUT_I64_TO_ADDR(wasm_argv, 0x8);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2,
wasm_argv));
i64 = 0x201F1E1D3C3B6AA9;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
}
TEST_P(memory64_atomic_test_suite, atomic_opcodes_i64_rmw_cmpxchg)
{
// from address 0, it's \01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10
PUT_I64_TO_ADDR(wasm_argv, 0x8);
// old
PUT_I64_TO_ADDR(wasm_argv + 2, 0x100F0E0D0C0B0A09);
// new
PUT_I64_TO_ADDR(wasm_argv + 4, 0xdeadcafebeefdead);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_rmw_cmpxchg"],
6, wasm_argv));
i64 = 0x100F0E0D0C0B0A09;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
PUT_I64_TO_ADDR(wasm_argv, 0x8);
ASSERT_TRUE(wasm_runtime_call_wasm(exec_env, func_map["i64_atomic_load"], 2,
wasm_argv));
i64 = 0xdeadcafebeefdead;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
}
INSTANTIATE_TEST_CASE_P(RunningMode, memory64_atomic_test_suite,
testing::ValuesIn(running_mode_supported));

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef UNIT_TEST_MEMORY64_COMMON_H
#define UNIT_TEST_MEMORY64_COMMON_H
#include "test_helper.h"
#include "gtest/gtest.h"
#include "platform_common.h"
#include "wasm_runtime_common.h"
#include "bh_read_file.h"
#include "wasm_runtime.h"
#include "bh_platform.h"
#include "wasm_export.h"
#include <unordered_map>
// #include "aot_runtime.h"
namespace {
std::vector<RunningMode> running_mode_supported = { Mode_Interp,
#if WASM_ENABLE_FAST_JIT != 0
Mode_Fast_JIT,
#endif
#if WASM_ENABLE_JIT != 0
Mode_LLVM_JIT,
#endif
#if WASM_ENABLE_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \
&& WASM_ENABLE_LAZY_JIT != 0
Mode_Multi_Tier_JIT
#endif
};
static inline uint64
GET_U64_FROM_ADDR(uint32 *addr)
{
union {
uint64 val;
uint32 parts[2];
} u;
u.parts[0] = addr[0];
u.parts[1] = addr[1];
return u.val;
}
static inline void
PUT_U64_TO_ADDR(uint32 *addr, uint64 value)
{
uint32 *addr_u32 = (uint32 *)(addr);
union {
float64 val;
uint32 parts[2];
} u;
u.val = (value);
addr_u32[0] = u.parts[0];
addr_u32[1] = u.parts[1];
}
}
#endif // UNIT_TEST_MEMORY64_COMMON_H

View File

@ -0,0 +1,235 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "memory64_common.h"
// To use a test fixture and Value Parameterized Tests,
// derive a class from testing::TestWithParam.
class memory64_test_suite : public testing::TestWithParam<RunningMode>
{
protected:
bool load_wasm_file(const char *wasm_file)
{
const char *file;
unsigned char *wasm_file_buf;
uint32 wasm_file_size;
file = wasm_file;
wasm_file_buf =
(unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size);
if (!wasm_file_buf)
goto fail;
if (!(module = wasm_runtime_load(wasm_file_buf, wasm_file_size,
error_buf, sizeof(error_buf)))) {
printf("Load wasm module failed. error: %s\n", error_buf);
goto fail;
}
return true;
fail:
if (!module)
wasm_runtime_unload(module);
return false;
}
bool init_exec_env()
{
if (!(module_inst =
wasm_runtime_instantiate(module, stack_size, heap_size,
error_buf, sizeof(error_buf)))) {
printf("Instantiate wasm module failed. error: %s\n", error_buf);
goto fail;
}
if (!(exec_env =
wasm_runtime_create_exec_env(module_inst, stack_size))) {
printf("Create wasm execution environment failed.\n");
goto fail;
}
return true;
fail:
if (exec_env)
wasm_runtime_destroy_exec_env(exec_env);
if (module_inst)
wasm_runtime_unload(module);
return false;
}
void destory_exec_env()
{
wasm_runtime_destroy_exec_env(exec_env);
wasm_runtime_deinstantiate(module_inst);
wasm_runtime_unload(module);
}
public:
// If your test fixture defines SetUpTestSuite() or TearDownTestSuite()
// they must be declared public rather than protected in order to use
// TEST_P.
// virtual void SetUp() will be called before each test is run. You
// should define it if you need to initialize the varaibles.
// Otherwise, this can be skipped.
virtual void SetUp()
{
memset(&init_args, 0, sizeof(RuntimeInitArgs));
init_args.mem_alloc_type = Alloc_With_Pool;
init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
ASSERT_EQ(wasm_runtime_full_init(&init_args), true);
cleanup = true;
}
static void SetUpTestCase() {}
// virtual void TearDown() will be called after each test is run.
// You should define it if there is cleanup work to do. Otherwise,
// you don't have to provide it.
//
virtual void TearDown()
{
if (cleanup) {
wasm_runtime_destroy();
cleanup = false;
}
}
static void TearDownTestCase() {}
RuntimeInitArgs init_args;
wasm_module_t module = NULL;
wasm_module_inst_t module_inst = NULL;
wasm_exec_env_t exec_env = NULL;
char error_buf[128];
char global_heap_buf[512 * 1024];
uint32_t stack_size = 8092, heap_size = 8092;
bool cleanup = true;
};
TEST_F(memory64_test_suite, wasm_runtime_is_running_mode_supported)
{
// TODO: make sure the chosen running mode option is compiled, for memory64,
// currently only support classic interp mode
ASSERT_EQ(true, wasm_runtime_is_running_mode_supported(
static_cast<RunningMode>(Mode_Default)));
for (auto running_mode : running_mode_supported) {
ASSERT_EQ(true, wasm_runtime_is_running_mode_supported(running_mode));
}
}
TEST_F(memory64_test_suite, page_exceed_u32_1)
{
bool ret;
ret = load_wasm_file("page_exceed_u32.wasm");
ASSERT_FALSE(ret);
ASSERT_TRUE(strcmp("WASM module load failed: integer too large", error_buf)
== 0);
}
TEST_F(memory64_test_suite, page_exceed_u32_2)
{
bool ret;
ret = load_wasm_file("page_exceed_u32_2.wasm");
ASSERT_FALSE(ret);
ASSERT_TRUE(strcmp("WASM module load failed: integer too large", error_buf)
== 0);
}
TEST_F(memory64_test_suite, page_u32_max)
{
bool ret;
ret = load_wasm_file("page_u32_max.wasm");
ASSERT_TRUE(ret);
}
TEST_P(memory64_test_suite, memory_8GB)
{
RunningMode running_mode = GetParam();
wasm_function_inst_t touch_every_page_func, i64_store_offset_4GB,
i64_load_offset_4GB;
uint32_t wasm_argv[6], i32;
uint64_t i64;
bool ret;
ret = load_wasm_file("8GB_memory.wasm");
ASSERT_TRUE(ret);
ret = init_exec_env();
ASSERT_TRUE(ret);
ret = wasm_runtime_set_running_mode(module_inst, running_mode);
ASSERT_TRUE(ret);
ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst));
touch_every_page_func =
wasm_runtime_lookup_function(module_inst, "touch_every_page");
ASSERT_TRUE(touch_every_page_func != NULL);
ret = wasm_runtime_call_wasm(exec_env, touch_every_page_func, 0, wasm_argv);
ASSERT_TRUE(ret);
// check return value: 0xfff8:i64,0x10000fff8:i64,0x1fff8:i32,0x1:i32
i64 = 0xfff8;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
i64 = 0x10000fff8;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv + 2));
i32 = 0x1fff8;
ASSERT_EQ(i32, wasm_argv[4]);
i32 = 0x1;
ASSERT_EQ(i32, wasm_argv[5]);
// store at 0x100001000, with value 0xbeefdead
PUT_I64_TO_ADDR(wasm_argv, 0x1000);
PUT_I64_TO_ADDR(wasm_argv + 2, 0xbeefdead);
i64_store_offset_4GB =
wasm_runtime_lookup_function(module_inst, "i64_store_offset_4GB");
ASSERT_TRUE(i64_store_offset_4GB != NULL);
ret = wasm_runtime_call_wasm(exec_env, i64_store_offset_4GB, 4, wasm_argv);
ASSERT_TRUE(ret);
i64_load_offset_4GB =
wasm_runtime_lookup_function(module_inst, "i64_load_offset_4GB");
ASSERT_TRUE(i64_load_offset_4GB != NULL);
ret = wasm_runtime_call_wasm(exec_env, i64_load_offset_4GB, 2, wasm_argv);
ASSERT_TRUE(ret);
// check return value: 0xbeefdead:i64
i64 = 0xbeefdead;
ASSERT_EQ(i64, GET_U64_FROM_ADDR(wasm_argv));
destory_exec_env();
}
TEST_P(memory64_test_suite, mem64_from_clang)
{
RunningMode running_mode = GetParam();
wasm_function_inst_t test_func;
uint32_t wasm_argv[1], i32;
bool ret;
ret = load_wasm_file("mem64.wasm");
ASSERT_TRUE(ret);
ret = init_exec_env();
ASSERT_TRUE(ret);
ret = wasm_runtime_set_running_mode(module_inst, running_mode);
ASSERT_TRUE(ret);
ASSERT_EQ(running_mode, wasm_runtime_get_running_mode(module_inst));
test_func =
wasm_runtime_lookup_function(module_inst, "test");
ASSERT_TRUE(test_func != NULL);
ret = wasm_runtime_call_wasm(exec_env, test_func, 0, wasm_argv);
ASSERT_TRUE(ret);
i32 = 0x109;
ASSERT_EQ(i32, wasm_argv[0]);
destory_exec_env();
}
INSTANTIATE_TEST_CASE_P(RunningMode, memory64_test_suite,
testing::ValuesIn(running_mode_supported));

Binary file not shown.

View File

@ -0,0 +1,53 @@
(module
;; Memory definition: 4 GB = 65536
;; 8 GB = 131072
;; 16 GB = 262144
;; 20 GB = 327680
;; 32 GB = 524288
(memory (;0;) i64 131072 131072)
;; if touch too many pages more than physical memory can provide,
;; the signal will kill the process
(func (export "touch_every_page") (result i64 i64 i32 i32)
(local $i i64)
i64.const 0x0000000000000ff8
local.set $i
loop $loop
;; a[i] = i
local.get $i
local.get $i
i64.store
local.get $i
i64.const 4096
i64.add
local.set $i
local.get $i
;; max boundary(exclusive) 8GB - 8 = 0x0000000200000000 - 8
i64.const 0x0000000200000000
i64.const 8
i64.sub
i64.lt_u
br_if $loop
end
i64.const 0x000000000000fff8
i64.load
i64.const 0x000000010000fff8
i64.load
;; lower 8 bytes of 0x000000010001fff8 -> 0x0001fff8
i64.const 0x000000010001fff8
i32.load
;; higher 8 bytes of 0x000000010001fff8 -> 0x1
i64.const 0x000000010001fffc
i32.load
return
)
;; Function to test i64.atomic.store with i64 address
(func (export "i64_store_offset_4GB") (param $addr i64) (param $value i64)
(i64.store offset=0x100000000 (local.get $addr) (local.get $value))
)
(func (export "i64_load_offset_4GB") (param $addr i64) (result i64)
(i64.load offset=0x100000000 (local.get $addr))
)
)

Binary file not shown.

View File

@ -0,0 +1,120 @@
(module
;; Memory definition: 4 GB = 65536
;; 8 GB = 131072
;; 16 GB = 262144
;; 20 GB = 327680
(memory (;0;) i64 200 200 shared)
;; Initialize memory with some values
(data (i64.const 0) "\01\02\03\04\05\06\07\08\09\0A\0B\0C\0D\0E\0F\10")
;; Function to test i32.atomic.store with i64 address
(func (export "i32_atomic_store") (param $addr i64) (param $value i32)
(i32.atomic.store (local.get $addr) (local.get $value))
)
;; Function to test i32.atomic.store8 with i64 address
(func (export "i32_atomic_store8") (param $addr i64) (param $value i32)
(i32.atomic.store8 (local.get $addr) (local.get $value))
)
;; Function to test i32.atomic.store16 with i64 address
(func (export "i32_atomic_store16") (param $addr i64) (param $value i32)
(i32.atomic.store16 (local.get $addr) (local.get $value))
)
;; Function to test i64.atomic.store with i64 address
(func (export "i64_atomic_store") (param $addr i64) (param $value i64)
(i64.atomic.store (local.get $addr) (local.get $value))
)
;; Function to test i64.atomic.store8 with i64 address
(func (export "i64_atomic_store8") (param $addr i64) (param $value i64)
(i64.atomic.store8 (local.get $addr) (local.get $value))
)
;; Function to test i64.atomic.store16 with i64 address
(func (export "i64_atomic_store16") (param $addr i64) (param $value i64)
(i64.atomic.store16 (local.get $addr) (local.get $value))
)
;; Function to test i64.atomic.store32 with i64 address
(func (export "i64_atomic_store32") (param $addr i64) (param $value i64)
(i64.atomic.store32 (local.get $addr) (local.get $value))
)
;; Function to test i32.atomic.load with i64 address
(func (export "i32_atomic_load") (param $addr i64) (result i32)
(i32.atomic.load (local.get $addr))
)
;; Function to test i32.atomic.load8_u with i64 address
(func (export "i32_atomic_load8_u") (param $addr i64) (result i32)
(i32.atomic.load8_u (local.get $addr))
)
;; Function to test i32.atomic.load16_u with i64 address
(func (export "i32_atomic_load16_u") (param $addr i64) (result i32)
(i32.atomic.load16_u (local.get $addr))
)
;; Function to test i64.atomic.load with i64 address
(func (export "i64_atomic_load") (param $addr i64) (result i64)
(i64.atomic.load (local.get $addr))
)
;; Function to test i64.atomic.load8_u with i64 address
(func (export "i64_atomic_load8_u") (param $addr i64) (result i64)
(i64.atomic.load8_u (local.get $addr))
)
;; Function to test i64.atomic.load16_u with i64 address
(func (export "i64_atomic_load16_u") (param $addr i64) (result i64)
(i64.atomic.load16_u (local.get $addr))
)
;; Function to test i64.atomic.load32_u with i64 address
(func (export "i64_atomic_load32_u") (param $addr i64) (result i64)
(i64.atomic.load32_u (local.get $addr))
)
;; Function to test i32.atomic.rmw.add with i64 address
(func (export "i32_atomic_rmw_add") (param $addr i64) (param $value i32) (result i32)
(i32.atomic.rmw.add (local.get $addr) (local.get $value))
)
;; Function to test i32.atomic.rmw8.add_u with i64 address
(func (export "i32_atomic_rmw8_add_u") (param $addr i64) (param $value i32) (result i32)
(i32.atomic.rmw8.add_u (local.get $addr) (local.get $value))
)
;; Function to test i32.atomic.rmw16.add_u with i64 address
(func (export "i32_atomic_rmw16_add_u") (param $addr i64) (param $value i32) (result i32)
(i32.atomic.rmw16.add_u (local.get $addr) (local.get $value))
)
;; Function to test i64.atomic.rmw.add with i64 address
(func (export "i64_atomic_rmw_add") (param $addr i64) (param $value i64) (result i64)
(i64.atomic.rmw.add (local.get $addr) (local.get $value))
)
;; Function to test i64.atomic.rmw8.add_u with i64 address
(func (export "i64_atomic_rmw8_add_u") (param $addr i64) (param $value i64) (result i64)
(i64.atomic.rmw8.add_u (local.get $addr) (local.get $value))
)
;; Function to test i64.atomic.rmw16.add_u with i64 address
(func (export "i64_atomic_rmw16_add_u") (param $addr i64) (param $value i64) (result i64)
(i64.atomic.rmw16.add_u (local.get $addr) (local.get $value))
)
;; Function to test i64.atomic.rmw32.add_u with i64 address
(func (export "i64_atomic_rmw32_add_u") (param $addr i64) (param $value i64) (result i64)
(i64.atomic.rmw32.add_u (local.get $addr) (local.get $value))
)
(func (export "i64_atomic_rmw_cmpxchg") (param $addr i64) (param $old i64) (param $new i64) (result i64)
(i64.atomic.rmw.cmpxchg (local.get $addr) (local.get $old) (local.get $new))
)
)

View File

@ -0,0 +1,56 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
int
add_a_and_b_to_c(int *array, int *b, int *c)
{
int i;
// Perform computation: multiply each element by 2
for (i = 0; i < 5; i++) {
array[i] = array[i] * 2;
}
// Compute the product of corresponding elements of a and b
for (i = 0; i < 5; i++) {
c[i] = array[i] * b[i];
}
return i;
}
int
test()
{
// Initialize an array with some values
int array[5] = { 1, 2, 3, 4, 5 };
int b[5] = { 6, 7, 8, 9, 10 };
int c[5], i, j, res = 0;
j = add_a_and_b_to_c(array, b, c);
for (i = 0; i < 5; i++) {
res += c[i];
}
return res + j;
}
int
main(int argc, char *argv[])
{
// Initialize an array with some values
int array[5] = { 1, 2, 3, 4, 5 };
int b[5] = { 6, 7, 8, 9, 10 };
int c[5], i;
// Perform computation: multiply each element by 2
for (i = 0; i < 5; i++) {
array[i] = array[i] * 2;
}
// Compute the product of corresponding elements of a and b
for (i = 0; i < 5; i++) {
c[i] = array[i] * b[i];
}
return c[4];
}

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,4 @@
(module
;; u32 max pages is 4,294,967,295
(memory i64 1 4294967296)
)

Binary file not shown.

View File

@ -0,0 +1,4 @@
(module
;; u32 max pages is 4,294,967,295
(memory i64 4294967296)
)

Binary file not shown.

View File

@ -0,0 +1,4 @@
(module
;; u32 max pages is 4,294,967,295
(memory i64 1 4294967295)
)