Quellcode durchsuchen

add more unit test cases for interpreter (#4716)

Co-authored-by: ai-assistant
Zhenwei Jin vor 3 Wochen
Ursprung
Commit
ae2fd0754b

+ 1 - 0
tests/unit/CMakeLists.txt

@@ -64,6 +64,7 @@ add_subdirectory(linux-perf)
 add_subdirectory(gc)
 add_subdirectory(tid-allocator)
 add_subdirectory(unsupported-features)
+add_subdirectory(smart-tests)
 
 if (NOT WAMR_BUILD_TARGET STREQUAL "X86_32")
   add_subdirectory(aot-stack-frame)

+ 4 - 0
tests/unit/smart-tests/CMakeLists.txt

@@ -0,0 +1,4 @@
+# Enhanced Unit Test CMakeLists.txt
+cmake_minimum_required(VERSION 3.12)
+
+add_subdirectory(interpreter)

+ 51 - 0
tests/unit/smart-tests/interpreter/CMakeLists.txt

@@ -0,0 +1,51 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 3.14)
+
+project (smart-test-interpreter)
+
+add_definitions (-DRUN_ON_LINUX)
+
+add_definitions (-Dattr_container_malloc=malloc)
+add_definitions (-Dattr_container_free=free)
+# add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1)
+
+set(WAMR_BUILD_AOT 0)
+set(WAMR_BUILD_INTERP 1)
+set(WAMR_BUILD_JIT 0)
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_APP_FRAMEWORK 1)
+
+include (../../unit_common.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+  ${UNIT_SOURCE}
+  ${WAMR_RUNTIME_LIB_SOURCE}
+)
+
+add_executable (smart_test_classic-interpreter ${unit_test_sources})
+target_compile_definitions(smart_test_classic-interpreter PUBLIC -DWAMR_BUILD_FAST_INTERP=0)
+target_link_libraries (smart_test_classic-interpreter gtest_main)
+
+add_executable (smart_test_fast-interpreter ${unit_test_sources})
+target_compile_definitions(smart_test_fast-interpreter PUBLIC -DWAMR_BUILD_FAST_INTERP=1)
+target_link_libraries (smart_test_fast-interpreter gtest_main)
+
+# Copy WASM files to build directory for classic interpreter
+# fast interpreter uses the same WASM files
+add_custom_command(TARGET smart_test_classic-interpreter POST_BUILD
+    COMMAND ${CMAKE_COMMAND} -E copy
+    ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/*.wasm
+    ${CMAKE_CURRENT_BINARY_DIR}/
+    COMMENT "Copy test wasm files to the directory of google test"
+)
+
+gtest_discover_tests(smart_test_classic-interpreter)
+gtest_discover_tests(smart_test_fast-interpreter)

+ 454 - 0
tests/unit/smart-tests/interpreter/interpreter_test_enhance.cc

@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2024 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+ #include "test_helper.h"
+ #include "gtest/gtest.h"
+ 
+ #include <unistd.h>
+ #include <fstream>
+ #include "wasm_runtime_common.h"
+ #include "wasm_runtime.h"
+ #include "wasm_interp.h"
+ #include "wasm_loader.h"
+ 
+ static std::string CWD;
+ static std::string WASM_FILE;
+ static constexpr uint32_t STACK_SIZE = 8092;
+ static constexpr uint32_t HEAP_SIZE = 8092;
+ 
+ static int
+ test_import_add_impl(wasm_exec_env_t exec_env, int32_t a, int32_t b)
+ {
+     return a + b;
+ }
+ 
+ static int
+ test_import_mul_impl(wasm_exec_env_t exec_env, int32_t a, int32_t b)
+ {
+     return a * b;
+ }
+ 
+ static int
+ malloc_impl(wasm_exec_env_t exec_env, int32_t size)
+ {
+     return wasm_runtime_module_malloc(
+         wasm_runtime_get_module_inst(exec_env), size, NULL);
+ }
+ 
+ static void
+ free_impl(wasm_exec_env_t exec_env, int32_t ptr)
+ {
+     wasm_runtime_module_free(
+         wasm_runtime_get_module_inst(exec_env), ptr);
+ }
+ 
+ static int
+ native_func_impl(wasm_exec_env_t exec_env, int32_t a)
+ {
+     return a * 2;
+ }
+ 
+ static NativeSymbol native_symbols[] = {
+     { "test_import_add", (void*)test_import_add_impl, "(ii)i", NULL },
+     { "test_import_mul", (void*)test_import_mul_impl, "(ii)i", NULL },
+     { "malloc", (void*)malloc_impl, "(i)i", NULL },
+     { "free", (void*)free_impl, "(i)", NULL },
+     { "native_func", (void*)native_func_impl, "(i)i", NULL }
+ };
+ 
+ /**
+  * Test fixture for Step 3: Function Invocation and Stack Operations
+  * Targets 6 functions: call_indirect, wasm_call_indirect, wasm_interp_call_func_import,
+  * copy_stack_values, execute_malloc_function, execute_free_function
+  */
+ class FunctionInvocationTest : public testing::Test
+ {
+ protected:
+     void SetUp() override
+     {
+         char *current_dir = getcwd(NULL, 0);
+         CWD = std::string(current_dir);
+         free(current_dir);
+         WASM_FILE = CWD + "/function_invocation_test.wasm";
+ 
+         memset(&init_args, 0, sizeof(RuntimeInitArgs));
+         init_args.mem_alloc_type = Alloc_With_System_Allocator;
+ 
+         ASSERT_TRUE(wasm_runtime_full_init(&init_args));
+ 
+         // Register native symbols for import testing
+         ASSERT_TRUE(wasm_runtime_register_natives("env", native_symbols,
+                                                   sizeof(native_symbols) / sizeof(NativeSymbol)));
+ 
+         load_wasm_file();
+         instantiate_module();
+     }
+ 
+     void TearDown() override
+     {
+         if (exec_env) {
+             wasm_runtime_destroy_exec_env(exec_env);
+         }
+         if (module_inst) {
+             wasm_runtime_deinstantiate(module_inst);
+         }
+         if (module) {
+             wasm_runtime_unload(module);
+         }
+         if (wasm_file_buf) {
+             delete[] wasm_file_buf;
+         }
+         wasm_runtime_destroy();
+     }
+ 
+     void load_wasm_file()
+     {
+         std::ifstream wasm_file(WASM_FILE, std::ios::binary);
+         ASSERT_TRUE(wasm_file.is_open()) << "Failed to open WASM file: " << WASM_FILE;
+         
+         std::vector<uint8_t> buffer(std::istreambuf_iterator<char>(wasm_file), {});
+         wasm_file_size = buffer.size();
+         wasm_file_buf = new unsigned char[wasm_file_size];
+         std::copy(buffer.begin(), buffer.end(), wasm_file_buf);
+ 
+         module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+         ASSERT_NE(module, nullptr) << "Load module failed: " << error_buf;
+     }
+ 
+     void instantiate_module()
+     {
+         module_inst = wasm_runtime_instantiate(
+             module, STACK_SIZE, HEAP_SIZE, error_buf, sizeof(error_buf));
+         ASSERT_NE(module_inst, nullptr) << "Instantiate module failed: " << error_buf;
+ 
+         exec_env = wasm_runtime_create_exec_env(module_inst, STACK_SIZE);
+         ASSERT_NE(exec_env, nullptr);
+     }
+ 
+     RuntimeInitArgs init_args;
+     wasm_module_t module = nullptr;
+     wasm_module_inst_t module_inst = nullptr;
+     wasm_exec_env_t exec_env = nullptr;
+     unsigned char *wasm_file_buf = nullptr;
+     uint32_t wasm_file_size = 0;
+     char error_buf[128] = { 0 };
+ };
+ 
+ /**
+  * Test Function 1: call_indirect() - Valid function call
+  * Target: core/iwasm/interpreter/wasm_runtime.c:call_indirect()
+  * Expected Coverage: ~15 lines (success path)
+  */
+ TEST_F(FunctionInvocationTest, CallIndirect_ValidFunction_ReturnsCorrectResult)
+ {
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_call_indirect_valid");
+     ASSERT_NE(func, nullptr);
+ 
+     uint32_t wasm_argv[2];
+     wasm_argv[0] = 0;  // table index 0 (points to $add_func)
+     wasm_argv[1] = 15; // parameter value
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv);
+     ASSERT_TRUE(success);
+ 
+     // $add_func adds 10 to input: 15 + 10 = 25
+     ASSERT_EQ(wasm_argv[0], 25);
+ }
+ 
+ /**
+  * Test Function 1: call_indirect() - Invalid index
+  * Target: core/iwasm/interpreter/wasm_runtime.c:call_indirect()
+  * Expected Coverage: ~15 lines (error path)
+  */
+ TEST_F(FunctionInvocationTest, CallIndirect_InvalidIndex_FailsGracefully)
+ {
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_call_indirect_invalid_index");
+     ASSERT_NE(func, nullptr);
+ 
+     uint32_t wasm_argv[1];
+     wasm_argv[0] = 42; // input value
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 1, wasm_argv);
+     ASSERT_FALSE(success);
+     ASSERT_TRUE(wasm_runtime_get_exception(module_inst) != NULL);
+ }
+ 
+ /**
+  * Test Function 2: wasm_call_indirect() - Type mismatch error handling
+  * Target: core/iwasm/interpreter/wasm_runtime.c:wasm_call_indirect()
+  * Expected Coverage: ~13 lines (error path)
+  */
+ TEST_F(FunctionInvocationTest, WasmCallIndirect_TypeMismatch_ReturnsFailure)
+ {
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_call_indirect_type_mismatch");
+     ASSERT_NE(func, nullptr);
+ 
+     uint32_t wasm_argv[1];
+     wasm_argv[0] = 100; // input value
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 1, wasm_argv);
+     ASSERT_FALSE(success);
+     ASSERT_TRUE(wasm_runtime_get_exception(module_inst) != NULL);
+ }
+ 
+ /**
+  * Test Function 3: wasm_interp_call_func_import() - Success path
+  * Target: core/iwasm/interpreter/wasm_interp_fast.c:wasm_interp_call_func_import()
+  * Expected Coverage: ~12 lines (success path)
+  */
+ TEST_F(FunctionInvocationTest, CallFuncImport_Success_CallsNativeFunction)
+ {
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_import_function_call");
+     ASSERT_NE(func, nullptr);
+ 
+     uint32_t wasm_argv[2];
+     wasm_argv[0] = 15; // first parameter
+     wasm_argv[1] = 25; // second parameter
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv);
+     ASSERT_TRUE(success);
+ 
+     // test_import_add_impl adds two values: 15 + 25 = 40
+     ASSERT_EQ(wasm_argv[0], 40);
+ }
+ 
+ /**
+  * Test Function 3: wasm_interp_call_func_import() - Multiple import calls
+  * Target: core/iwasm/interpreter/wasm_interp_fast.c:wasm_interp_call_func_import()
+  * Expected Coverage: ~13 lines (additional path)
+  */
+ TEST_F(FunctionInvocationTest, CallFuncImport_MultipleImports_HandlesCorrectly)
+ {
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_import_function_mul");
+     ASSERT_NE(func, nullptr);
+ 
+     uint32_t wasm_argv[2];
+     wasm_argv[0] = 6; // first parameter
+     wasm_argv[1] = 7; // second parameter
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv);
+     ASSERT_TRUE(success);
+ 
+     // test_import_mul_impl multiplies two values: 6 * 7 = 42
+     ASSERT_EQ(wasm_argv[0], 42);
+ }
+ 
+ /**
+  * Test Function 4: copy_stack_values() - Normal operation
+  * Target: core/iwasm/interpreter/wasm_interp_fast.c:copy_stack_values()
+  * Expected Coverage: ~20 lines (normal operation)
+  */
+ TEST_F(FunctionInvocationTest, CopyStackValues_Normal_CopiesValuesCorrectly)
+ {
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_stack_operations");
+     ASSERT_NE(func, nullptr);
+ 
+     uint32_t wasm_argv[2];
+     wasm_argv[0] = 10; // val1
+     wasm_argv[1] = 20; // val2
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv);
+     ASSERT_TRUE(success);
+ 
+     // Complex calculation: (10+20) + (5+10) + (20*3) = 30 + 15 + 60 = 105
+     ASSERT_EQ(wasm_argv[0], 105);
+ }
+ 
+ /**
+  * Test Function 4: copy_stack_values() - Large parameter count
+  * Target: core/iwasm/interpreter/wasm_interp_fast.c:copy_stack_values()
+  * Expected Coverage: Additional lines for large stack operations
+  */
+ TEST_F(FunctionInvocationTest, CopyStackValues_LargeParams_HandlesCorrectly)
+ {
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_large_param_stack");
+     ASSERT_NE(func, nullptr);
+ 
+     uint32_t wasm_argv[8];
+     wasm_argv[0] = 1;
+     wasm_argv[1] = 2;
+     wasm_argv[2] = 3;
+     wasm_argv[3] = 4;
+     wasm_argv[4] = 5;
+     wasm_argv[5] = 6;
+     wasm_argv[6] = 7;
+     wasm_argv[7] = 8;
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 8, wasm_argv);
+     ASSERT_TRUE(success);
+ 
+     // (1+2) + (3+4) + (5+6) + (7+8) = 3 + 7 + 11 + 15 = 36
+     ASSERT_EQ(wasm_argv[0], 36);
+ }
+ 
+ /**
+  * Test Function 5: execute_malloc_function() - Success path
+  * Target: core/iwasm/interpreter/wasm_runtime.c:execute_malloc_function()
+  * Expected Coverage: ~20 lines (success path)
+  */
+ TEST_F(FunctionInvocationTest, ExecuteMalloc_Success_AllocatesMemory)
+ {
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_malloc_operation");
+     ASSERT_NE(func, nullptr);
+ 
+     uint32_t wasm_argv[1];
+     wasm_argv[0] = 1024; // allocate 1KB
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 1, wasm_argv);
+     ASSERT_TRUE(success);
+ 
+     // Should return a valid memory offset (> 0)
+     ASSERT_GT(wasm_argv[0], 0);
+ }
+ 
+ /**
+  * Test Function 5: execute_malloc_function() - Failure path
+  * Target: core/iwasm/interpreter/wasm_runtime.c:execute_malloc_function()
+  * Expected Coverage: ~20 lines (failure path)
+  */
+ TEST_F(FunctionInvocationTest, ExecuteMalloc_Failure_HandlesLargeAllocation)
+ {
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_malloc_operation");
+     ASSERT_NE(func, nullptr);
+ 
+     uint32_t wasm_argv[1];
+     wasm_argv[0] = 0x10000000; // try to allocate large amount (256MB)
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 1, wasm_argv);
+     // The call should succeed (no crash), but malloc should return 0
+     ASSERT_TRUE(success);
+     ASSERT_EQ(wasm_argv[0], 0);
+ }
+ 
+ /**
+  * Test Function 6: execute_free_function() - Success path
+  * Target: core/iwasm/interpreter/wasm_runtime.c:execute_free_function()
+  * Expected Coverage: ~20 lines (success path)
+  */
+ TEST_F(FunctionInvocationTest, ExecuteFree_Success_FreesMemory)
+ {
+     // First allocate memory
+     wasm_function_inst_t malloc_func = wasm_runtime_lookup_function(
+         module_inst, "test_malloc_operation");
+     ASSERT_NE(malloc_func, nullptr);
+ 
+     uint32_t malloc_argv[1];
+     malloc_argv[0] = 512;
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, malloc_func, 1, malloc_argv);
+     ASSERT_TRUE(success);
+     ASSERT_GT(malloc_argv[0], 0);
+ 
+     // Now free the allocated memory
+     wasm_function_inst_t free_func = wasm_runtime_lookup_function(
+         module_inst, "test_free_operation");
+     ASSERT_NE(free_func, nullptr);
+ 
+     uint32_t free_argv[1];
+     free_argv[0] = malloc_argv[0]; // use allocated pointer
+ 
+     success = wasm_runtime_call_wasm(exec_env, free_func, 1, free_argv);
+     ASSERT_TRUE(success);
+ }
+ 
+ /**
+  * Test Function 6: execute_free_function() - Error handling
+  * Target: core/iwasm/interpreter/wasm_runtime.c:execute_free_function()
+  * Expected Coverage: ~20 lines (error path)
+  */
+ TEST_F(FunctionInvocationTest, ExecuteFree_ErrorHandling_HandlesInvalidPointer)
+ {
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_free_operation");
+     ASSERT_NE(func, nullptr);
+ 
+     uint32_t wasm_argv[1];
+     wasm_argv[0] = 0; // try to free NULL pointer
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 1, wasm_argv);
+     ASSERT_TRUE(success); // free(NULL) is valid and should succeed
+ }
+ 
+ /**
+  * Test malloc/free cycle to exercise both functions together
+  */
+ TEST_F(FunctionInvocationTest, MallocFreeCycle_Complete_WorksCorrectly)
+ {
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_malloc_free_cycle");
+     ASSERT_NE(func, nullptr);
+ 
+     uint32_t wasm_argv[1];
+     wasm_argv[0] = 256; // allocation size
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 1, wasm_argv);
+     ASSERT_TRUE(success);
+ 
+     // Should return the value that was stored (42)
+     ASSERT_EQ(wasm_argv[0], 42);
+ }
+ 
+ /**
+  * Test complex indirect call scenarios
+  */
+ TEST_F(FunctionInvocationTest, ComplexIndirectCalls_MultipleSelectors_HandlesCorrectly)
+ {
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_complex_indirect_calls");
+     ASSERT_NE(func, nullptr);
+ 
+     // Test selector 0 (add_func)
+     uint32_t wasm_argv[2];
+     wasm_argv[0] = 0;  // selector
+     wasm_argv[1] = 30; // value
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv);
+     ASSERT_TRUE(success);
+     ASSERT_EQ(wasm_argv[0], 40); // 30 + 10 = 40
+ 
+     // Test selector 1 (mul_func)
+     wasm_argv[0] = 1;  // selector
+     wasm_argv[1] = 15; // value
+ 
+     success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv);
+     ASSERT_TRUE(success);
+     ASSERT_EQ(wasm_argv[0], 30); // 15 * 2 = 30
+ 
+     // Test selector 2 (identity_func)
+     wasm_argv[0] = 2;  // selector
+     wasm_argv[1] = 99; // value
+ 
+     success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv);
+     ASSERT_TRUE(success);
+     ASSERT_EQ(wasm_argv[0], 99); // identity returns same value
+ }
+ 
+ /**
+  * Additional test for function invocation edge cases
+  */
+ TEST_F(FunctionInvocationTest, FunctionInvocation_EdgeCases_HandlesCorrectly)
+ {
+     // Test with maximum parameter values
+     wasm_function_inst_t func = wasm_runtime_lookup_function(
+         module_inst, "test_stack_operations");
+     ASSERT_NE(func, nullptr);
+ 
+     uint32_t wasm_argv[2];
+     wasm_argv[0] = 0xFFFFFFFF; // max uint32
+     wasm_argv[1] = 1;
+ 
+     bool success = wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv);
+     ASSERT_TRUE(success);
+ }

BIN
tests/unit/smart-tests/interpreter/wasm-apps/function_invocation_test.wasm


+ 150 - 0
tests/unit/smart-tests/interpreter/wasm-apps/function_invocation_test.wat

@@ -0,0 +1,150 @@
+(module
+  ;; Import functions
+  (import "env" "test_import_add" (func $test_import_add (param i32 i32) (result i32)))
+  (import "env" "test_import_mul" (func $test_import_mul (param i32 i32) (result i32)))
+  (import "env" "malloc" (func $malloc (param i32) (result i32)))
+  (import "env" "free" (func $free (param i32)))
+  (import "env" "native_func" (func $native_func (param i32) (result i32)))
+  
+  ;; Type definitions
+  (type $void_to_void (func))
+  (type $i32_to_i32 (func (param i32) (result i32)))
+  (type $i32_i32_to_i32 (func (param i32 i32) (result i32)))
+  
+  ;; Memory and table
+  (memory 1)
+  (table 4 funcref)
+  
+  ;; Local functions for table
+  (func $add_func (type $i32_to_i32) (param $x i32) (result i32)
+    local.get $x
+    i32.const 10
+    i32.add)
+  
+  (func $mul_func (type $i32_to_i32) (param $x i32) (result i32)
+    local.get $x
+    i32.const 2
+    i32.mul)
+  
+  (func $identity_func (type $i32_to_i32) (param $x i32) (result i32)
+    local.get $x)
+  
+  (func $void_func (type $void_to_void))
+  
+  ;; Initialize table
+  (elem (i32.const 0) $add_func $mul_func $identity_func $void_func)
+  
+  ;; Test functions matching the C++ test expectations
+  (func (export "test_call_indirect_valid") (param $idx i32) (param $val i32) (result i32)
+    local.get $val
+    local.get $idx
+    call_indirect (type $i32_to_i32))
+  
+  (func (export "test_call_indirect_invalid_index") (param $val i32) (result i32)
+    local.get $val
+    i32.const 10
+    call_indirect (type $i32_to_i32))
+  
+  (func (export "test_call_indirect_type_mismatch") (param $val i32) (result i32)
+    local.get $val
+    i32.const 3
+    call_indirect (type $i32_to_i32))
+  
+  (func (export "test_import_function_call") (param $a i32) (param $b i32) (result i32)
+    local.get $a
+    local.get $b
+    call $test_import_add)
+  
+  (func (export "test_import_function_mul") (param $a i32) (param $b i32) (result i32)
+    local.get $a
+    local.get $b
+    call $test_import_mul)
+  
+  (func (export "test_native_function_call") (param $a i32) (result i32)
+    local.get $a
+    call $native_func)
+  
+  (func (export "test_malloc_operation") (param $size i32) (result i32)
+    local.get $size
+    call $malloc)
+  
+  (func (export "test_free_operation") (param $ptr i32)
+    local.get $ptr
+    call $free)
+  
+  (func (export "test_malloc_free_cycle") (param $size i32) (result i32)
+    (local $ptr i32)
+    local.get $size
+    call $malloc
+    local.set $ptr
+    
+    local.get $ptr
+    i32.const 42
+    i32.store
+    
+    local.get $ptr
+    i32.load
+    
+    local.get $ptr
+    call $free)
+  
+  (func (export "test_stack_operations") (param $val1 i32) (param $val2 i32) (result i32)
+    local.get $val1
+    local.get $val2
+    call $test_import_add
+    
+    i32.const 5
+    call $add_func
+    i32.add
+    
+    local.get $val2
+    i32.const 3
+    call $test_import_mul
+    i32.add)
+  
+  (func (export "test_complex_indirect_calls") (param $selector i32) (param $value i32) (result i32)
+    local.get $selector
+    i32.const 0
+    i32.eq
+    if (result i32)
+      local.get $value
+      i32.const 0
+      call_indirect (type $i32_to_i32)
+    else
+      local.get $selector
+      i32.const 1
+      i32.eq
+      if (result i32)
+        local.get $value
+        i32.const 1
+        call_indirect (type $i32_to_i32)
+      else
+        local.get $value
+        i32.const 2
+        call_indirect (type $i32_to_i32)
+      end
+    end)
+  
+  (func (export "test_large_param_stack") 
+    (param $p1 i32) (param $p2 i32) (param $p3 i32) (param $p4 i32)
+    (param $p5 i32) (param $p6 i32) (param $p7 i32) (param $p8 i32)
+    (result i32)
+    local.get $p1
+    local.get $p2
+    call $test_import_add
+    
+    local.get $p3
+    local.get $p4
+    call $test_import_add
+    i32.add
+    
+    local.get $p5
+    local.get $p6
+    call $test_import_add
+    i32.add
+    
+    local.get $p7
+    local.get $p8
+    call $test_import_add
+    i32.add)
+)