Enable aarch64 support, add component test framework and test suite (#211)

and refine aot call indirect op
This commit is contained in:
wenyongh 2020-03-24 19:04:29 +08:00 committed by GitHub
parent 8ae161b779
commit 01e85144f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
77 changed files with 3293 additions and 288 deletions

View File

@ -37,6 +37,7 @@ The iwasm supports the following architectures:
- X86-64, X86-32
- ARM, THUMB (ARMV7 Cortex-M7 and Cortex-A15 are tested)
- AArch64 (Cortex-A57 and Cortex-A53 are tested)
- MIPS
- XTENSA

View File

@ -27,6 +27,9 @@ elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*")
add_definitions(-DBUILD_TARGET_THUMB)
add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}")
endif ()
elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*")
add_definitions(-DBUILD_TARGET_AARCH64)
add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}")
elseif (WAMR_BUILD_TARGET STREQUAL "MIPS")
add_definitions(-DBUILD_TARGET_MIPS)
elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
@ -40,7 +43,7 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
endif ()
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*")
# Add -fPIC flag if build as 64-bit
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")

View File

@ -31,7 +31,7 @@ endif ()
# Set default options
# Set WAMR_BUILD_TARGET, currently values supported:
# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
if (NOT DEFINED WAMR_BUILD_TARGET)
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
# Build as X86_64 by default in 64-bit platform

View File

@ -8,6 +8,7 @@
#if !defined(BUILD_TARGET_X86_64) \
&& !defined(BUILD_TARGET_AMD_64) \
&& !defined(BUILD_TARGET_AARCH64) \
&& !defined(BUILD_TARGET_X86_32) \
&& !defined(BUILD_TARGET_ARM) \
&& !defined(BUILD_TARGET_ARM_VFP) \
@ -19,6 +20,8 @@
#define BUILD_TARGET_X86_64
#elif defined(__amd64__) || defined(__amd64)
#define BUILD_TARGET_AMD_64
#elif defined(__aarch64__)
#define BUILD_TARGET_AARCH64
#elif defined(__i386__) || defined(__i386) || defined(i386)
#define BUILD_TARGET_X86_32
#elif defined(__thumb__)

View File

@ -140,6 +140,7 @@ GET_U64_FROM_ADDR(uint32 *addr)
#define E_MACHINE_MIPS 8 /* MIPS R3000 big-endian */
#define E_MACHINE_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */
#define E_MACHINE_ARM 40 /* ARM/Thumb */
#define E_MACHINE_AARCH64 183 /* AArch64 */
#define E_MACHINE_ARC 45 /* Argonaut RISC Core */
#define E_MACHINE_IA_64 50 /* Intel Merced */
#define E_MACHINE_MIPS_X 51 /* Stanford MIPS-X */
@ -196,6 +197,7 @@ get_aot_file_target(AOTTargetInfo *target_info,
machine_type = "i386";
break;
case E_MACHINE_ARM:
case E_MACHINE_AARCH64:
machine_type = target_info->arch;
break;
case E_MACHINE_MIPS:

View File

@ -14,9 +14,8 @@ typedef struct {
#define REG_COMMON_SYMBOLS \
REG_SYM(aot_set_exception_with_id), \
REG_SYM(aot_get_exception), \
REG_SYM(aot_is_wasm_type_equal), \
REG_SYM(aot_invoke_native), \
REG_SYM(aot_call_indirect), \
REG_SYM(wasm_runtime_enlarge_memory), \
REG_SYM(wasm_runtime_set_exception), \
REG_SYM(fmin), \

View File

@ -811,7 +811,7 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
return wasm_type_equal(type1, type2);
}
void
bool
aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
uint32 *frame_lp, uint32 argc, uint32 *argv_ret)
{
@ -827,18 +827,76 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
const char *signature = NULL;
char buf[128];
if (func_idx < aot_module->import_func_count) {
import_func = aot_module->import_funcs + func_idx;
if (!func_ptr) {
snprintf(buf, sizeof(buf),
"fail to call unlinked import function (%s, %s)",
import_func->module_name, import_func->func_name);
aot_set_exception(module_inst, buf);
return;
}
signature = import_func->signature;
bh_assert(func_idx < aot_module->import_func_count);
import_func = aot_module->import_funcs + func_idx;
if (!func_ptr) {
snprintf(buf, sizeof(buf),
"fail to call unlinked import function (%s, %s)",
import_func->module_name, import_func->func_name);
aot_set_exception(module_inst, buf);
return false;
}
wasm_runtime_invoke_native(exec_env, func_ptr,
func_type, signature, frame_lp, argc, argv_ret);
signature = import_func->signature;
return wasm_runtime_invoke_native(exec_env, func_ptr,
func_type, signature,
frame_lp, argc, argv_ret);
}
bool
aot_call_indirect(WASMExecEnv *exec_env,
uint32 func_type_idx, uint32 table_elem_idx,
uint32 *frame_lp, uint32 argc, uint32 *argv_ret)
{
AOTModuleInstance *module_inst = (AOTModuleInstance*)
wasm_runtime_get_module_inst(exec_env);
AOTModule *aot_module = (AOTModule*)module_inst->aot_module.ptr;
uint32 *func_type_indexes = (uint32*)module_inst->func_type_indexes.ptr;
uint32 *table_data = (uint32*)module_inst->table_data.ptr;
AOTFuncType *func_type = aot_module->func_types[func_type_idx];;
void **func_ptrs = (void**)module_inst->func_ptrs.ptr, *func_ptr;
uint32 table_size = module_inst->table_size;
uint32 func_idx, func_type_idx1;
AOTImportFunc *import_func;
const char *signature = NULL;
char buf[128];
if (table_elem_idx >= table_size) {
aot_set_exception_with_id(module_inst, EXCE_UNDEFINED_ELEMENT);
return false;
}
func_idx = table_data[table_elem_idx];
if (func_idx == (uint32)-1) {
aot_set_exception_with_id(module_inst, EXCE_UNINITIALIZED_ELEMENT);
return false;
}
func_type_idx1 = func_type_indexes[func_idx];
if (!aot_is_wasm_type_equal(module_inst, func_type_idx, func_type_idx1)) {
aot_set_exception_with_id(module_inst, EXCE_INVALID_FUNCTION_TYPE_INDEX);
return false;
}
if (func_idx < aot_module->import_func_count) {
/* Call native function */
import_func = aot_module->import_funcs + func_idx;
signature = import_func->signature;
}
if (!(func_ptr = func_ptrs[func_idx])) {
bh_assert(func_idx < aot_module->import_func_count);
import_func = aot_module->import_funcs + func_idx;
snprintf(buf, sizeof(buf),
"fail to call unlinked import function (%s, %s)",
import_func->module_name, import_func->func_name);
aot_set_exception(module_inst, buf);
return false;
}
return wasm_runtime_invoke_native(exec_env, func_ptr,
func_type, signature,
frame_lp, argc, argv_ret);
}

View File

@ -435,10 +435,15 @@ aot_is_wasm_type_equal(AOTModuleInstance *module_inst,
/**
* Invoke native function from aot code
*/
void
bool
aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
uint32 *frame_lp, uint32 argc, uint32 *argv_ret);
bool
aot_call_indirect(WASMExecEnv *exec_env,
uint32 func_type_idx, uint32 table_elem_idx,
uint32 *frame_lp, uint32 argc, uint32 *argv_ret);
uint32
aot_get_plt_table_size();

View File

@ -0,0 +1,238 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "aot_reloc.h"
#define R_AARCH64_ADR_PREL_PG_HI21 275
#define R_AARCH64_ADD_ABS_LO12_NC 277
#define R_AARCH64_CALL26 283
static SymbolMap target_sym_map[] = {
REG_COMMON_SYMBOLS
};
static void
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
{
if (error_buf != NULL)
snprintf(error_buf, error_buf_size, "%s", string);
}
SymbolMap *
get_target_symbol_map(uint32 *sym_num)
{
*sym_num = sizeof(target_sym_map) / sizeof(SymbolMap);
return target_sym_map;
}
void
get_current_target(char *target_buf, uint32 target_buf_size)
{
char *build_target = BUILD_TARGET;
char *p = target_buf, *p_end;
snprintf(target_buf, target_buf_size, "%s", build_target);
p_end = p + strlen(target_buf);
while (p < p_end) {
if (*p >= 'A' && *p <= 'Z')
*p++ += 'a' - 'A';
else
p++;
}
if (!strcmp(target_buf, "aarch64"))
snprintf(target_buf, target_buf_size, "aarch64v8");
}
static uint32
get_plt_item_size()
{
/* 8*4 bytes instructions and 8 bytes symbol address */
return 40;
}
void
init_plt_table(uint8 *plt)
{
uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
for (i = 0; i < num; i++) {
uint32 *p = (uint32*)plt;
*p++ = 0xd10023ff; /* sub sp, sp, #0x8 */
*p++ = 0xf90003fe; /* str x30, [sp] */
*p++ = 0x100000de; /* adr x30, #24 */
*p++ = 0xf94003de; /* ldr x30, [x30] */
*p++ = 0xd63f03c0; /* blr x30 */
*p++ = 0xf94003fe; /* ldr x30, [sp] */
*p++ = 0x910023ff; /* add sp, sp, #0x8 */
*p++ = 0xd61f03c0; /* br x30 */
/* symbol addr */
*(uint64*)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr;
p += 2;
plt += get_plt_item_size();
}
}
uint32
get_plt_table_size()
{
return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
}
#define SIGN_EXTEND_TO_INT64(val, bits, val_ext) do { \
int64 m = ((int64)1 << (bits - 1)); \
val_ext = ((int64)val ^ m) - m; \
} while (0)
#define Page(expr) ((expr) & ~0xFFF)
static bool
check_reloc_offset(uint32 target_section_size,
uint64 reloc_offset, uint32 reloc_data_size,
char *error_buf, uint32 error_buf_size)
{
if (!(reloc_offset < (uint64)target_section_size
&& reloc_offset + reloc_data_size <= (uint64)target_section_size)) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: invalid relocation offset.");
return false;
}
return true;
}
bool
apply_relocation(AOTModule *module,
uint8 *target_section_addr, uint32 target_section_size,
uint64 reloc_offset, uint64 reloc_addend,
uint32 reloc_type, void *symbol_addr, int32 symbol_index,
char *error_buf, uint32 error_buf_size)
{
switch (reloc_type) {
case R_AARCH64_CALL26:
{
void *S, *P = (void*)(target_section_addr + reloc_offset);
int64 X, A, initial_addend;
int32 insn, imm26;
CHECK_RELOC_OFFSET(sizeof(int32));
insn = *(int32*)P;
imm26 = insn & 0x3FFFFFF;
SIGN_EXTEND_TO_INT64(imm26 << 2, 28, initial_addend);
A = initial_addend;
A += (int64)reloc_addend;
if (symbol_index < 0) {
/* Symbol address itself is an AOT function.
* Apply relocation with the symbol directly.
* Suppose the symbol address is in +-128MB relative
* to the relocation address.
*/
S = symbol_addr;
}
else {
uint8 *plt;
if (reloc_addend > 0) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: relocate to plt table "
"with reloc addend larger than 0 is unsupported.");
return false;
}
/* Symbol address is not an AOT function,
* but a function of runtime or native. Its address is
* beyond of the +-128MB space. Apply relocation with
* the PLT which branch to the target symbol address.
*/
S = plt = (uint8*)module->code + module->code_size
- get_plt_table_size()
+ get_plt_item_size() * symbol_index;
}
/* S + A - P */
X = (int64)S + A - (int64)P;
/* Check overflow: +-128MB */
if (X > (128 * BH_MB) || X < (-128 * BH_MB)) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"target address out of range.");
return false;
}
/* write the imm26 back to instruction */
*(int32*)P = (insn & 0xFC000000) | ((int32)((X >> 2) & 0x3FFFFFF));
break;
}
case R_AARCH64_ADR_PREL_PG_HI21:
{
void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
int64 X, A, initial_addend;
int32 insn, immhi19, immlo2, imm21;
CHECK_RELOC_OFFSET(sizeof(int32));
insn = *(int32*)P;
immhi19 = (insn >> 5) & 0x7FFFF;
immlo2 = (insn >> 29) & 0x3;
imm21 = (immhi19 << 2) | immlo2;
SIGN_EXTEND_TO_INT64(imm21 << 12, 33, initial_addend);
A = initial_addend;
A += (int64)reloc_addend;
/* Page(S+A) - Page(P) */
X = Page((int64)S + A) - Page((int64)P);
/* Check overflow: +-4GB */
if (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"target address out of range.");
return false;
}
/* write the imm21 back to instruction */
immhi19 = (int32)(((X >> 12) >> 2) & 0x7FFFF);
immlo2 = (int32)((X >> 12) & 0x3);
*(int32*)P = (insn & 0x9F00001F) | (immlo2 << 29) | (immhi19 << 5);
break;
}
case R_AARCH64_ADD_ABS_LO12_NC:
{
void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
int64 X, A, initial_addend;
int32 insn, imm12;
CHECK_RELOC_OFFSET(sizeof(int32));
insn = *(int32*)P;
imm12 = (insn >> 10) & 0xFFF;
SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend);
A = initial_addend;
A += (int64)reloc_addend;
/* S + A */
X = (int64)S + A;
/* No need to check overflow for this reloction type */
/* write the imm12 back to instruction */
*(int32*)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10));
break;
}
default:
if (error_buf != NULL)
snprintf(error_buf, error_buf_size,
"Load relocation section failed: "
"invalid relocation type %d.",
reloc_type);
return false;
}
return true;
}

View File

@ -9,10 +9,6 @@
#define R_ARM_JMP24 29 /* PC relative 24 bit (B/BL<cond>). */
#define R_ARM_ABS32 2 /* Direct 32 bit */
#ifndef BH_MB
#define BH_MB 1024 * 1024
#endif
void __divdi3();
void __udivdi3();
void __moddi3();
@ -163,7 +159,7 @@ init_plt_table(uint8 *plt)
/* nop */
*p++ = 0xe1a00000;
/* symbol addr */
*p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;;
*p++ = (uint32)(uintptr_t)target_sym_map[i].symbol_addr;
plt += get_plt_item_size();
}
}

View File

@ -8,10 +8,6 @@
#define R_ARM_THM_CALL 10 /* PC relative (Thumb BL and ARMv5 Thumb BLX). */
#define R_ARM_THM_JMP24 30 /* B.W */
#ifndef BH_MB
#define BH_MB 1024 * 1024
#endif
void __divdi3();
void __udivdi3();
void __moddi3();

View File

@ -13,6 +13,8 @@ if (${WAMR_BUILD_TARGET} STREQUAL "X86_64" OR ${WAMR_BUILD_TARGET} STREQUAL "AMD
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_64.c)
elseif (${WAMR_BUILD_TARGET} STREQUAL "X86_32")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_x86_32.c)
elseif (${WAMR_BUILD_TARGET} MATCHES "AARCH64.*")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_aarch64.c)
elseif (${WAMR_BUILD_TARGET} MATCHES "ARM.*")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_arm.c)
elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*")

View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
.text
.align 2
.global invokeNative
.type invokeNative,function
/*
* Arguments passed in:
*
* x0 function ptr
* x1 argv
* x2 nstacks
*/
invokeNative:
sub sp, sp, #0x30
stp x19, x20, [sp, #0x20] /* save the registers */
stp x21, x22, [sp, #0x10]
stp x23, x24, [sp, #0x0]
mov x19, x0 /* x19 = function ptr */
mov x20, x1 /* x20 = argv */
mov x21, x2 /* x21 = nstacks */
mov x22, sp /* save the sp before call function */
/* Fill in float-point registers */
ldp d0, d1, [x20], #16 /* d0 = argv[0], d1 = argv[1] */
ldp d2, d3, [x20], #16 /* d2 = argv[2], d3 = argv[3] */
ldp d4, d5, [x20], #16 /* d4 = argv[4], d5 = argv[5] */
ldp d6, d7, [x20], #16 /* d6 = argv[6], d7 = argv[7] */
/* Fill inteter registers */
ldp x0, x1, [x20], #16 /* x0 = argv[8] = exec_env, x1 = argv[9] */
ldp x2, x3, [x20], #16 /* x2 = argv[10], x3 = argv[11] */
ldp x4, x5, [x20], #16 /* x4 = argv[12], x5 = argv[13] */
ldp x6, x7, [x20], #16 /* x6 = argv[14], x7 = argv[15] */
/* Now x20 points to stack args */
/* Directly call the fucntion if no args in stack */
cmp x21, #0
beq call_func
/* Fill all stack args: reserve stack space and fill ony by one */
mov x23, sp
bic sp, x23, #15 /* Ensure stack is 16 bytes aligned */
lsl x23, x21, #3 /* x23 = nstacks * 8 */
add x23, x23, #15 /* x23 = (x23 + 15) & ~15 */
bic x23, x23, #15
sub sp, sp, x23 /* reserved stack space for stack arguments */
mov x23, sp
loop_stack_args: /* copy stack arguments to stack */
cmp x21, #0
beq call_func
ldr x24, [x20], #8
str x24, [x23], #8
sub x21, x21, #1
b loop_stack_args
call_func:
mov x20, x30 /* save x30(lr) */
blr x19
mov sp, x22 /* restore sp which is saved before calling fuction*/
return:
mov x30, x20 /* restore x30(lr) */
ldp x19, x20, [sp, #0x20] /* restore the registers in stack */
ldp x21, x22, [sp, #0x10]
ldp x23, x24, [sp, #0x0]
add sp, sp, #0x30 /* restore sp */
ret

View File

@ -26,6 +26,8 @@ elseif (${WAMR_BUILD_TARGET} MATCHES "THUMB.*")
else ()
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb.s)
endif ()
elseif (${WAMR_BUILD_TARGET} MATCHES "AARCH64.*")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64.s)
elseif (${WAMR_BUILD_TARGET} STREQUAL "MIPS")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mips.s)
elseif (${WAMR_BUILD_TARGET} STREQUAL "XTENSA")

View File

@ -1811,7 +1811,9 @@ fail:
|| defined(BUILD_TARGET_MIPS) \
|| defined(BUILD_TARGET_XTENSA) */
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
#if defined(BUILD_TARGET_X86_64) \
|| defined(BUILD_TARGET_AMD_64) \
|| defined(BUILD_TARGET_AARCH64)
typedef void (*GenericFunctionPointer)();
int64 invokeNative(GenericFunctionPointer f, uint64 *args, uint64 n_stacks);
@ -1832,8 +1834,12 @@ static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)(uintptr_t)invokeNative;
#define MAX_REG_INTS 4
#else
#define MAX_REG_FLOATS 8
#if defined(BUILD_TARGET_AARCH64)
#define MAX_REG_INTS 8
#else
#define MAX_REG_INTS 6
#endif
#endif /* end of defined(BUILD_TARGET_AARCH64 */
#endif /* end of defined(_WIN32) || defined(_WIN32_) */
bool
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
@ -1963,4 +1969,6 @@ fail:
return ret;
}
#endif /* end of defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) */
#endif /* end of defined(BUILD_TARGET_X86_64) \
|| defined(BUILD_TARGET_AMD_64) \
|| defined(BUILD_TARGET_AARCH64) */

View File

@ -8,41 +8,17 @@
#include "aot_emit_control.h"
#include "../aot/aot_runtime.h"
/* Check whether there was exception thrown, if yes, return directly */
static bool
check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
create_func_return_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
{
LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
LLVMBasicBlockRef block_curr, check_exce_succ;
LLVMValueRef value, cmp;
/* Load the first byte of aot_module_inst->cur_exception, and check
whether it is '\0'. If yes, no exception was thrown. */
if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception,
"exce_value"))
|| !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
value, I8_ZERO, "cmp"))) {
aot_set_last_error("llvm build icmp failed.");
return false;
}
/* Add check exection success block */
if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_exce_succ"))) {
aot_set_last_error("llvm add basic block failed.");
return false;
}
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
LLVMMoveBasicBlockAfter(check_exce_succ, block_curr);
/* Create function return block if it isn't created */
if (!func_ctx->func_return_block) {
if (!(func_ctx->func_return_block =
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"func_ret"))) {
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func, "func_ret"))) {
aot_set_last_error("llvm add basic block failed.");
return false;
}
@ -70,6 +46,42 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
}
}
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
return true;
}
/* Check whether there was exception thrown, if yes, return directly */
static bool
check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
{
LLVMBasicBlockRef block_curr, check_exce_succ;
LLVMValueRef value, cmp;
/* Create function return block if it isn't created */
if (!create_func_return_block(comp_ctx, func_ctx))
return false;
/* Load the first byte of aot_module_inst->cur_exception, and check
whether it is '\0'. If yes, no exception was thrown. */
if (!(value = LLVMBuildLoad(comp_ctx->builder, func_ctx->cur_exception,
"exce_value"))
|| !(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
value, I8_ZERO, "cmp"))) {
aot_set_last_error("llvm build icmp failed.");
return false;
}
/* Add check exection success block */
if (!(check_exce_succ = LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_exce_succ"))) {
aot_set_last_error("llvm add basic block failed.");
return false;
}
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
LLVMMoveBasicBlockAfter(check_exce_succ, block_curr);
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
/* Create condition br */
if (!LLVMBuildCondBr(comp_ctx->builder, cmp,
@ -82,18 +94,59 @@ check_exception_thrown(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
return true;
}
/* Check whether there was exception thrown, if yes, return directly */
static bool
check_call_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMValueRef res)
{
LLVMBasicBlockRef block_curr, check_call_succ;
LLVMValueRef cmp;
/* Create function return block if it isn't created */
if (!create_func_return_block(comp_ctx, func_ctx))
return false;
if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE,
res, I8_ZERO, "cmp"))) {
aot_set_last_error("llvm build icmp failed.");
return false;
}
/* Add check exection success block */
if (!(check_call_succ = LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_exce_succ"))) {
aot_set_last_error("llvm add basic block failed.");
return false;
}
block_curr = LLVMGetInsertBlock(comp_ctx->builder);
LLVMMoveBasicBlockAfter(check_call_succ, block_curr);
LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
/* Create condition br */
if (!LLVMBuildCondBr(comp_ctx->builder, cmp,
check_call_succ, func_ctx->func_return_block)) {
aot_set_last_error("llvm build cond br failed.");
return false;
}
LLVMPositionBuilderAtEnd(comp_ctx->builder, check_call_succ);
return true;
}
static bool
call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMValueRef func_idx, AOTFuncType *aot_func_type,
LLVMTypeRef *param_types, LLVMValueRef *param_values,
uint32 param_count, uint32 param_cell_num,
LLVMTypeRef ret_type, uint8 wasm_ret_type,
LLVMValueRef *p_value_ret)
LLVMValueRef *p_value_ret, LLVMValueRef *p_res)
{
LLVMTypeRef func_type, func_ptr_type, func_param_types[5];
LLVMTypeRef ret_ptr_type, elem_ptr_type;
LLVMValueRef func, elem_idx, elem_ptr;
LLVMValueRef func_param_values[5], value_ret, value_ret_ptr, res;
LLVMValueRef func_param_values[5], value_ret = NULL, value_ret_ptr, res;
char buf[32], *func_name = "aot_invoke_native";
uint32 i, cell_num = 0;
@ -103,7 +156,7 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
func_param_types[2] = INT32_PTR_TYPE; /* frame_lp */
func_param_types[3] = I32_TYPE; /* argc */
func_param_types[4] = INT32_PTR_TYPE; /* argv_ret */
if (!(func_type = LLVMFunctionType(VOID_TYPE, func_param_types, 5, false))) {
if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 5, false))) {
aot_set_last_error("llvm add function type failed.");
return false;
}
@ -198,7 +251,8 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
}
/* call aot_invoke_native() function */
if (!(LLVMBuildCall(comp_ctx->builder, func, func_param_values, 5, ""))) {
if (!(res = LLVMBuildCall(comp_ctx->builder, func,
func_param_values, 5, "res"))) {
aot_set_last_error("llvm build call failed.");
return false;
}
@ -207,6 +261,7 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
/* get function return value */
*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret");
*p_res = res;
return true;
}
@ -221,7 +276,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
AOTFuncType *func_type;
LLVMTypeRef *param_types = NULL, ret_type;
LLVMValueRef *param_values = NULL, value_ret = NULL, func;
LLVMValueRef import_func_idx;
LLVMValueRef import_func_idx, res;
int32 i, j = 0, param_count;
uint64 total_size;
uint8 wasm_ret_type;
@ -292,13 +347,17 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
if (!call_aot_invoke_native_func(comp_ctx, func_ctx, import_func_idx, func_type,
param_types + 1, param_values + 1,
param_count, param_cell_num,
ret_type, wasm_ret_type, &value_ret))
ret_type, wasm_ret_type, &value_ret, &res))
goto fail;
/* Check whether there was exception thrown when executing the function */
if (!check_call_return(comp_ctx, func_ctx, res))
goto fail;
}
else {
func = func_ctxes[func_idx - import_func_count]->func;
/* Call the function */
/* Call the function */
if (!(value_ret = LLVMBuildCall(comp_ctx->builder, func,
param_values, (uint32)param_count + 1,
(func_type->result_count > 0
@ -309,15 +368,15 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
/* Set calling convention for the call with the func's calling convention */
LLVMSetInstructionCallConv(value_ret, LLVMGetFunctionCallConv(func));
/* Check whether there was exception thrown when executing the function */
if (!check_exception_thrown(comp_ctx, func_ctx))
goto fail;
}
if (func_type->result_count > 0)
PUSH(value_ret, func_type->types[func_type->param_count]);
/* Check whether there was exception thrown when executing the function */
if (!check_exception_thrown(comp_ctx, func_ctx))
goto fail;
ret = true;
fail:
if (param_types)
@ -327,21 +386,148 @@ fail:
return ret;
}
static bool
call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
AOTFuncType *aot_func_type,
LLVMValueRef func_type_idx, LLVMValueRef table_elem_idx,
LLVMTypeRef *param_types, LLVMValueRef *param_values,
uint32 param_count, uint32 param_cell_num,
LLVMTypeRef ret_type, uint8 wasm_ret_type,
LLVMValueRef *p_value_ret, LLVMValueRef *p_res)
{
LLVMTypeRef func_type, func_ptr_type, func_param_types[6];
LLVMTypeRef ret_ptr_type, elem_ptr_type;
LLVMValueRef func, elem_idx, elem_ptr;
LLVMValueRef func_param_values[6], value_ret = NULL, value_ret_ptr, res = NULL;
char buf[32], *func_name = "aot_call_indirect";
uint32 i, cell_num = 0;
/* prepare function type of aot_call_indirect */
func_param_types[0] = comp_ctx->exec_env_type; /* exec_env */
func_param_types[1] = I32_TYPE; /* func_type_idx */
func_param_types[2] = I32_TYPE; /* table_elem_idx */
func_param_types[3] = INT32_PTR_TYPE; /* frame_lp */
func_param_types[4] = I32_TYPE; /* argc */
func_param_types[5] = INT32_PTR_TYPE; /* argv_ret */
if (!(func_type = LLVMFunctionType(INT8_TYPE, func_param_types, 6, false))) {
aot_set_last_error("llvm add function type failed.");
return false;
}
/* prepare function pointer */
if (comp_ctx->is_jit_mode) {
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
aot_set_last_error("create LLVM function type failed.");
return false;
}
/* JIT mode, call the function directly */
if (!(func = I64_CONST((uint64)(uintptr_t)aot_call_indirect))
|| !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
aot_set_last_error("create LLVM value failed.");
return false;
}
}
else {
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
&& !(func = LLVMAddFunction(comp_ctx->module,
func_name, func_type))) {
aot_set_last_error("add LLVM function failed.");
return false;
}
}
if (param_count > 64) {
aot_set_last_error("prepare native arguments failed: "
"maximum 64 parameter cell number supported.");
return false;
}
/* prepare frame_lp */
for (i = 0; i < param_count; i++) {
if (!(elem_idx = I32_CONST(cell_num))
|| !(elem_ptr_type = LLVMPointerType(param_types[i], 0))) {
aot_set_last_error("llvm add const or pointer type failed.");
return false;
}
snprintf(buf, sizeof(buf), "%s%d", "elem", i);
if (!(elem_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
func_ctx->argv_buf, &elem_idx, 1, buf))
|| !(elem_ptr = LLVMBuildBitCast(comp_ctx->builder, elem_ptr,
elem_ptr_type, buf))) {
aot_set_last_error("llvm build bit cast failed.");
return false;
}
if (!(res = LLVMBuildStore(comp_ctx->builder, param_values[i], elem_ptr))) {
aot_set_last_error("llvm build store failed.");
return false;
}
LLVMSetAlignment(res, 1);
cell_num += wasm_value_type_cell_num(aot_func_type->types[i]);
}
if (wasm_ret_type != VALUE_TYPE_VOID) {
if (!(ret_ptr_type = LLVMPointerType(ret_type, 0))) {
aot_set_last_error("llvm add pointer type failed.");
return false;
}
if (!(value_ret = LLVMBuildBitCast(comp_ctx->builder, func_ctx->argv_buf,
ret_ptr_type, "argv_ret"))) {
aot_set_last_error("llvm build bit cast failed.");
return false;
}
/* convert to int32 pointer */
if (!(value_ret_ptr = LLVMBuildBitCast(comp_ctx->builder, value_ret,
INT32_PTR_TYPE, "argv_ret_ptr"))) {
aot_set_last_error("llvm build store failed.");
return false;
}
}
else {
value_ret_ptr = LLVMConstNull(INT32_PTR_TYPE);
}
func_param_values[0] = func_ctx->exec_env;
func_param_values[1] = func_type_idx;
func_param_values[2] = table_elem_idx;
func_param_values[3] = func_ctx->argv_buf;
func_param_values[4] = I32_CONST(param_cell_num);
func_param_values[5] = value_ret_ptr;
if (!func_param_values[4]) {
aot_set_last_error("llvm create const failed.");
return false;
}
/* call aot_call_indirect() function */
if (!(res = LLVMBuildCall(comp_ctx->builder, func,
func_param_values, 6, "res"))) {
aot_set_last_error("llvm build call failed.");
return false;
}
if (wasm_ret_type != VALUE_TYPE_VOID)
/* get function return value */
*p_value_ret = LLVMBuildLoad(comp_ctx->builder, value_ret, "value_ret");
*p_res = res;
return true;
}
bool
aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
uint32 type_idx)
{
AOTFuncType *func_type;
LLVMValueRef elem_idx, table_elem, func_idx, ftype_idx_ptr, ftype_idx;
LLVMValueRef cmp_elem_idx, cmp_func_idx, is_ftype_match, is_ftype_mismatch;
LLVMValueRef func, func_ptr, func_const, table_size_const, cmp_func_ptr;
LLVMValueRef *param_values = NULL, param_values_tmp[3], value_ret;
LLVMTypeRef *param_types = NULL, param_types_tmp[3], ret_type,
f_type, f_ptr_type;
LLVMBasicBlockRef check_elem_idx_succ, check_ftype_idx_succ;
LLVMBasicBlockRef check_func_idx_succ, check_func_ptr_succ;
char *func_name = "aot_is_wasm_type_equal";
int32 i, j = 0, param_count;
LLVMValueRef elem_idx, ftype_idx;
LLVMValueRef *param_values = NULL, value_ret = NULL, res = NULL;
LLVMTypeRef *param_types = NULL, ret_type;
int32 i, param_count;
uint32 param_cell_num;
uint64 total_size;
uint8 wasm_ret_type;
@ -353,210 +539,26 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return false;
}
ftype_idx = I32_CONST(type_idx);
CHECK_LLVM_CONST(ftype_idx);
func_type = comp_ctx->comp_data->func_types[type_idx];
param_cell_num = wasm_type_param_cell_num(func_type);
POP_I32(elem_idx);
table_size_const = I32_CONST(comp_ctx->comp_data->table_size);
CHECK_LLVM_CONST(table_size_const);
/* Check if (uint32)elem index >= table size */
if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE,
elem_idx, table_size_const,
"cmp_elem_idx"))) {
aot_set_last_error("llvm build icmp failed.");
goto fail;
}
/* Throw exception if elem index >= table size */
if (!(check_elem_idx_succ =
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_elem_idx_succ"))) {
aot_set_last_error("llvm add basic block failed.");
goto fail;
}
LLVMMoveBasicBlockAfter(check_elem_idx_succ,
LLVMGetInsertBlock(comp_ctx->builder));
if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNDEFINED_ELEMENT,
true, cmp_elem_idx, check_elem_idx_succ)))
goto fail;
/* Load function index */
if (!(table_elem = LLVMBuildInBoundsGEP(comp_ctx->builder,
func_ctx->table_base,
&elem_idx, 1, "table_elem"))) {
aot_set_last_error("llvm build add failed.");
goto fail;
}
if (!(func_idx = LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) {
aot_set_last_error("llvm build load failed.");
goto fail;
}
/* Check if func_idx == -1 */
if (!(cmp_func_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
func_idx, I32_NEG_ONE,
"cmp_func_idx"))) {
aot_set_last_error("llvm build icmp failed.");
goto fail;
}
/* Throw exception if func_idx == -1 */
if (!(check_func_idx_succ =
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_func_idx_succ"))) {
aot_set_last_error("llvm add basic block failed.");
goto fail;
}
LLVMMoveBasicBlockAfter(check_func_idx_succ,
LLVMGetInsertBlock(comp_ctx->builder));
if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_UNINITIALIZED_ELEMENT,
true, cmp_func_idx, check_func_idx_succ)))
goto fail;
/* Load function type index */
if (!(ftype_idx_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
func_ctx->func_type_indexes,
&func_idx, 1,
"ftype_idx_ptr"))) {
aot_set_last_error("llvm build inbounds gep failed.");
goto fail;
}
if (!(ftype_idx = LLVMBuildLoad(comp_ctx->builder, ftype_idx_ptr,
"ftype_idx"))) {
aot_set_last_error("llvm build load failed.");
goto fail;
}
/* Call aot_is_type_equal() to check whether function type match */
param_types_tmp[0] = INT8_PTR_TYPE;
param_types_tmp[1] = I32_TYPE;
param_types_tmp[2] = I32_TYPE;
ret_type = INT8_TYPE;
/* Create function type */
if (!(f_type = LLVMFunctionType(ret_type, param_types_tmp,
3, false))) {
aot_set_last_error("create LLVM function type failed.");
goto fail;
}
if (comp_ctx->is_jit_mode) {
/* Create function type */
if (!(f_ptr_type = LLVMPointerType(f_type, 0))) {
aot_set_last_error("create LLVM function type failed.");
goto fail;
}
/* Create LLVM function with const function pointer */
if (!(func_const = I64_CONST((uint64)(uintptr_t)aot_is_wasm_type_equal))
|| !(func = LLVMConstIntToPtr(func_const, f_ptr_type))) {
aot_set_last_error("create LLVM value failed.");
goto fail;
}
}
else {
/* Create LLVM function with external function pointer */
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
&& !(func = LLVMAddFunction(comp_ctx->module, func_name, f_type))) {
aot_set_last_error("add LLVM function failed.");
goto fail;
}
}
/* Call the aot_is_type_equal() function */
param_values_tmp[0] = func_ctx->aot_inst;
param_values_tmp[1] = I32_CONST(type_idx);
param_values_tmp[2] = ftype_idx;
CHECK_LLVM_CONST(param_values_tmp[1]);
if (!(is_ftype_match = LLVMBuildCall(comp_ctx->builder, func,
param_values_tmp, 3,
"is_ftype_match"))) {
aot_set_last_error("llvm build icmp failed.");
goto fail;
}
if (!(is_ftype_mismatch = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ,
is_ftype_match, I8_ZERO,
"is_ftype_mismatch"))) {
aot_set_last_error("llvm build icmp failed.");
goto fail;
}
if (!(check_ftype_idx_succ =
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_ftype_idx_success"))) {
aot_set_last_error("llvm add basic block failed.");
goto fail;
}
LLVMMoveBasicBlockAfter(check_ftype_idx_succ,
LLVMGetInsertBlock(comp_ctx->builder));
if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_INVALID_FUNCTION_TYPE_INDEX,
true, is_ftype_mismatch, check_ftype_idx_succ)))
goto fail;
/* Load function pointer */
if (!(func_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->func_ptrs,
&func_idx, 1, "func_ptr"))) {
aot_set_last_error("llvm build inbounds gep failed.");
goto fail;
}
if (!(func = LLVMBuildLoad(comp_ctx->builder, func_ptr, "func_tmp"))) {
aot_set_last_error("llvm build load failed.");
goto fail;
}
/* Check whether import function is NULL */
if (!(cmp_func_ptr = LLVMBuildIsNull(comp_ctx->builder, func, "is_func_null"))) {
aot_set_last_error("llvm build is null failed.");
goto fail;
}
/* Throw exception if import function is NULL */
if (!(check_func_ptr_succ =
LLVMAppendBasicBlockInContext(comp_ctx->context,
func_ctx->func,
"check_func_ptr_succ"))) {
aot_set_last_error("llvm add basic block failed.");
goto fail;
}
LLVMMoveBasicBlockAfter(check_func_ptr_succ,
LLVMGetInsertBlock(comp_ctx->builder));
if (!(aot_emit_exception(comp_ctx, func_ctx,
EXCE_CALL_UNLINKED_IMPORT_FUNC,
true, cmp_func_ptr, check_func_ptr_succ)))
goto fail;
/* Initialize parameter types of the LLVM function */
param_count = (int32)func_type->param_count;
total_size = sizeof(LLVMTypeRef) * (uint64)(param_count + 1);
total_size = sizeof(LLVMTypeRef) * (uint64)param_count;
if (total_size >= UINT32_MAX
|| !(param_types = wasm_runtime_malloc((uint32)total_size))) {
aot_set_last_error("Allocate memory failed.");
goto fail;
}
j = 0;
param_types[j++] = comp_ctx->exec_env_type;
for (i = 0; i < param_count; i++)
param_types[j++] = TO_LLVM_TYPE(func_type->types[i]);
param_types[i] = TO_LLVM_TYPE(func_type->types[i]);
/* Resolve return type of the LLVM function */
if (func_type->result_count) {
@ -569,32 +571,30 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
}
/* Allocate memory for parameters */
total_size = sizeof(LLVMValueRef) * (uint64)(param_count + 1);
total_size = sizeof(LLVMValueRef) * (uint64)param_count;
if (total_size >= UINT32_MAX
|| !(param_values = wasm_runtime_malloc((uint32)total_size))) {
aot_set_last_error("Allocate memory failed.");
goto fail;
}
/* First parameter is exec env */
j = 0;
param_values[j++] = func_ctx->exec_env;
/* Pop parameters from stack */
for (i = param_count - 1; i >= 0; i--)
POP(param_values[i + j], func_type->types[i]);
POP(param_values[i], func_type->types[i]);
if (!call_aot_invoke_native_func(comp_ctx, func_ctx, func_idx, func_type,
param_types + 1, param_values + 1,
if (!call_aot_call_indirect_func(comp_ctx, func_ctx,
func_type, ftype_idx, elem_idx,
param_types, param_values,
param_count, param_cell_num,
ret_type, wasm_ret_type, &value_ret))
ret_type, wasm_ret_type,
&value_ret, &res))
goto fail;
if (func_type->result_count > 0)
PUSH(value_ret, func_type->types[func_type->param_count]);
/* Check whether there was exception thrown when executing the function */
if (!check_exception_thrown(comp_ctx, func_ctx))
if (!check_call_return(comp_ctx, func_ctx, res))
goto fail;
ret = true;

View File

@ -741,6 +741,18 @@ static ArchItem valid_archs[] = {
{ "x86_64", false },
{ "i386", false },
{ "mips", true },
{ "aarch64v8", false },
{ "aarch64v8.1", false },
{ "aarch64v8.2", false },
{ "aarch64v8.3", false },
{ "aarch64v8.4", false },
{ "aarch64v8.5", false },
{ "aarch64_bev8", false }, /* big endian */
{ "aarch64_bev8.1", false },
{ "aarch64_bev8.2", false },
{ "aarch64_bev8.3", false },
{ "aarch64_bev8.4", false },
{ "aarch64_bev8.5", false },
{ "armv4", true },
{ "armv4t", true },
{ "armv5t", true },
@ -939,6 +951,10 @@ aot_create_comp_context(AOTCompData *comp_data,
arch = "thumbv4t";
else if (!strcmp(arch, "thumbeb"))
arch = "thumbv4teb";
else if (!strcmp(arch, "aarch64"))
arch = "aarch64v8";
else if (!strcmp(arch, "aarch64_be"))
arch = "aarch64_bev8";
}
/* Check target arch */

View File

@ -23,7 +23,7 @@ The script `runtime_lib.cmake` defined a number of variables for configuring the
- **WAMR_BUILD_PLATFORM**: set the target platform. It can be set to any platform name (folder name) under folder [core/shared/platform](../core/shared/platform).
- **WAMR_BUILD_TARGET**: set the target CPU architecture. Current supported targets: X86_64, X86_32, ARM, THUMB, XTENSA and MIPS. For ARM and THUMB, the format is <arch>[<sub-arch>][_VFP] where <sub-arch> is the ARM sub-architecture and the "_VFP" suffix means VFP coprocessor registers s0-s15 (d0-d7) are used for passing arguments or returning results in standard procedure-call. Both <sub-arch> and [_VFP] are optional. e.g. ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on.
- **WAMR_BUILD_TARGET**: set the target CPU architecture. Current supported targets: X86_64, X86_32, AArch64, ARM, THUMB, XTENSA and MIPS. For AArch64, ARM and THUMB, the format is <arch>[<sub-arch>][_VFP] where <sub-arch> is the ARM sub-architecture and the "_VFP" suffix means VFP coprocessor registers s0-s15 (d0-d7) are used for passing arguments or returning results in standard procedure-call. Both <sub-arch> and "_VFP" are optional. e.g. AARCH64, AARCH64V8, AARCHV8.1, ARMV7, ARMV7_VFP, THUMBV7, THUMBV7_VFP and so on.
```bash
cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM
@ -229,6 +229,10 @@ source ../../zephyr-env.sh
``` Bash
./build.sh stm32
```
3. build for AArch64 (qemu_cortex_a53)
``` Bash
./build.sh qemu_cortex_a53
```
Note:
WAMR provides some features which can be easily configured by passing options to cmake, please see [Linux platform](./build_wamr.md#linux) for details. Currently in Zephyr, interpreter, AoT and builtin libc are enabled by default.
@ -272,6 +276,7 @@ AliOS-Things
aos make helloworld@linuxhost -c config
aos make
./out/helloworld@linuxhost/binary/helloworld@linuxhost.elf
```
```
For developerkit:
@ -279,8 +284,8 @@ AliOS-Things
``` C
WAMR_BUILD_TARGET := THUMBV7M
```
```
``` Bash
aos make helloworld@developerkit -c config
aos make

View File

@ -27,7 +27,7 @@ set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
# Set WAMR_BUILD_TARGET, currently values supported:
# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
if (NOT DEFINED WAMR_BUILD_TARGET)
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
# Build as X86_64 by default in 64-bit platform

View File

@ -12,7 +12,7 @@ set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
# Set WAMR_BUILD_TARGET, currently values supported:
# "X86_64", "AMD_64", "X86_32", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
if (NOT DEFINED WAMR_BUILD_TARGET)
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
# Build as X86_64 by default in 64-bit platform

View File

@ -10,7 +10,7 @@ enable_language (ASM)
set (WAMR_BUILD_PLATFORM "zephyr")
# Build as X86_32 by default, change to "ARM[sub]", "THUMB[sub]", "MIPS" or "XTENSA"
# Build as X86_32 by default, change to "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS" or "XTENSA"
# if we want to support arm, thumb, mips or xtensa
if (NOT DEFINED WAMR_BUILD_TARGET)
set (WAMR_BUILD_TARGET "X86_32")

View File

@ -5,13 +5,15 @@
X86_TARGET="x86"
STM32_TARGET="stm32"
QEMU_CORTEX_A53="qemu_cortex_a53"
if [ $# != 1 ] ; then
echo "USAGE:"
echo "$0 $X86_TARGET|$STM32_TARGET"
echo "$0 $X86_TARGET|$STM32_TARGET|$QEMU_CORTEX_A53"
echo "Example:"
echo " $0 $X86_TARGET"
echo " $0 $STM32_TARGET"
echo " $0 $QEMU_CORTEX_A53"
exit 1
fi
@ -29,6 +31,12 @@ elif [ "$TARGET" = "$STM32_TARGET" ] ; then
cmake -GNinja -DBOARD=nucleo_f767zi -DWAMR_BUILD_TARGET=THUMBV7 ..
ninja
ninja flash
elif [ "$TARGET" = "$QEMU_CORTEX_A53" ] ; then
cp prj_qemu_cortex_a53.conf prj.conf
rm -fr build && mkdir build && cd build
cmake -GNinja -DBOARD=qemu_cortex_a53 -DWAMR_BUILD_TARGET=AARCH64 ..
ninja
ninja run
else
echo "unsupported target: $TARGET"
exit 1

View File

@ -0,0 +1,7 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
CONFIG_ARM_MMU=n
CONFIG_STACK_SENTINEL=y
CONFIG_PRINTK=y
CONFIG_LOG=y

View File

@ -10,6 +10,9 @@ set (WAMR_BUILD_PLATFORM "zephyr")
enable_language (ASM)
add_definitions(-DWA_MALLOC=wasm_runtime_malloc)
add_definitions(-DWA_FREE=wasm_runtime_free)
# Build as THUMB by default
# change to "ARM[sub]", "THUMB[sub]", "X86_32", "MIPS" or "XTENSA"
# if we want to support arm_32, x86, mips or xtensa

View File

@ -345,7 +345,7 @@ static host_interface interface = { .send = uart_send, .destroy = uart_destroy }
#endif
#ifdef __x86_64__
static char global_heap_buf[400 * 1024] = { 0 };
static char global_heap_buf[420 * 1024] = { 0 };
#else
static char global_heap_buf[270 * 1024] = { 0 };
#endif

View File

@ -10,6 +10,9 @@ set (WAMR_BUILD_PLATFORM "zephyr")
enable_language (ASM)
add_definitions(-DWA_MALLOC=wasm_runtime_malloc)
add_definitions(-DWA_FREE=wasm_runtime_free)
# Build as THUMB by default
# change to "ARM[sub]", "THUMB[sub]", "X86_32", "MIPS_32" or "XTENSA_32"
# if we want to support arm_32, x86, mips or xtensa

View File

@ -0,0 +1,56 @@
# Component Test
The purpose of this test suite is to verify the basic components of WAMR work well in combination. It is highly recommended to run pass all suites before each commitment.
Prerequisites
==============
- clang is available to build wasm application.
- python is installed to run test script.
Run the test
=============
```
start.py [-h] [-s SUITE_ID [SUITE_ID ...]] [-t CASE_ID [CASE_ID ...]]
[-n REPEAT_TIME] [--shuffle_all]
[--cases_list CASES_LIST_FILE_PATH] [--skip_proc]
[-b BINARIES] [-d] [--rebuild]
```
It builds out the simple project binary including WAMR runtime binary ```simple``` and the testing tool ```host_tool``` before running the test suites.
Test output is like:
```
Test Execution Summary:
Success: 8
Cases fails: 0
Setup fails: 0
Case load fails: 0
------------------------------------------------------------
The run folder is [run-03-23-16-29]
that's all. bye
kill to quit..
Killed
```
The detailed report and log is generated in ```run``` folder. The binaries copy is also put in that folder.
Usage samples
==============
Run default test suite:
</br>
```python start.py```
Rebuild all test apps and then run default test suite:
</br>
```python start.py --rebuild```
Run a specified test suite:
</br>
```python start.py -s 01-life-cycle```
Run a specified test case:
</br>
```python start.py -t 01-install```

View File

@ -0,0 +1,11 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
__all__ = [
"net_manager", "wifi_daemon_utils"
]
__author__ = ""
__package__ = "model"
__version__ = "1.0"

View File

@ -0,0 +1,11 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
__all__ = [
"net_manager", "wifi_daemon_utils"
]
__author__ = ""
__package__ = "model"
__version__ = "1.0"

View File

@ -0,0 +1,29 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import os
import json
from test.test_support import _run_suite
class CTestCaseBase(object):
def __init__(self, suite):
self.m_suite = suite
return
def on_get_case_description(self):
return "Undefined"
def on_setup_case(self):
return True, ''
def on_cleanup_case(self):
return True, ''
# called by the framework
def on_run_case(self):
return True, ''
def get_suite(self):
return self.m_suite

View File

@ -0,0 +1,38 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import datetime
import os
import pprint
import random
import re
import shlex
import subprocess
import signal
import sys
import time
from .test_utils import *
from .test_api import *
def read_cases_from_file(file_path):
if not os.path.exists(file_path):
return False, None
with open(file_path, 'r') as f:
content = f.readlines()
content = [x.strip() for x in content]
print content
if len(content) == 0:
return False, None
return True, content

View File

@ -0,0 +1,287 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import datetime
import os
import pprint
import random
import re
import shlex
import subprocess
import signal
import sys
import time
import shutil
from .test_api import *
import this
'''
The run evironment dir structure:
run/
run{date-time}/
suites/
{suite name}/
-- target/ (the target software being tested)
-- tools/ (the tools for testing the target software)
'''
framework=None
def get_framework():
global framework
return framework
def my_import(name):
mod = __import__(name)
components = name.split('.')
for comp in components[1:]:
mod = getattr(mod, comp)
return mod
# we maintain a root path apart from framework location
# so the suites can be located in anywhere
class CTestFramework(object):
def __init__(self, path):
self.running_case = ''
self.running_suite = ''
self.target_suites = {}
self.target_cases = {}
self.root_path = path
self.running_folder=''
self.report = None
self.sucess_cases = 0
self.failed_cases = 0
self.setup_fails = 0
self.load_fails = 0;
global framework
framework = self
api_set_root_path(path)
print "root_path is " + self.root_path
def gen_execution_stats(self):
return '\nTest Execution Summary: ' \
'\n\tSuccess: {}' \
'\n\tCases fails: {}' \
'\n\tSetup fails: {}' \
'\n\tCase load fails: {}'.format(
self.sucess_cases, self.failed_cases, self.setup_fails, self.load_fails)
def report_result(self, success, message, case_description):
if self.report is None:
return
case_pass = "pass"
if not success:
case_pass = "fail"
self.report.write(case_pass + ": [" + self.running_case + "]\n\treason: " + \
message + "\n\tcase: " + case_description + "\n")
return
def get_running_path(self):
return self.root_path + "/run/" + self.running_folder
def load_suites(self):
self.target_suites = os.listdir(self.root_path + "/suites")
return
def run_case(self, suite_instance, case):
# load the test case module
case_description = ''
suite = suite_instance.m_name
api_log("\n>>start run [" + case + "] >>")
module_name = 'suites.' + suite + ".cases." + case + ".case"
try:
module = my_import(module_name)
except Exception, e:
report_fail("load case fail: " + str(e))
api_log_error("load case fail: " + str(e))
self.load_fails = self.load_fails +1
print(traceback.format_exc())
return False
try:
case = module.CTestCase(suite_instance)
except Exception, e:
report_fail("initialize case fail: " + str(e))
api_log_error("initialize case fail: " + str(e))
self.load_fails = self.load_fails +1
return False
# call the case on setup callback
try:
case_description = case.on_get_case_description()
result, message = case.on_setup_case()
except Exception, e:
result = False
message = str(e);
if not result:
api_log_error(message)
report_fail (message, case_description)
self.failed_cases = self.failed_cases+1
return False
# call the case execution callaback
try:
result, message = case.on_run_case()
except Exception, e:
result = False
message = str(e);
if not result:
report_fail (message, case_description)
api_log_error(message)
self.failed_cases = self.failed_cases+1
else:
report_success(case_description)
self.sucess_cases = self.sucess_cases +1
# call the case cleanup callback
try:
clean_result, message = case.on_cleanup_case()
except Exception, e:
clean_result = False
message = str(e)
if not clean_result:
api_log(message)
return result
def run_suite(self, suite, cases):
# suite setup
message = ''
api_log("\n>>> Suite [" + suite + "] starting >>>")
running_folder = self.get_running_path()+ "/suites/" + suite;
module_name = 'suites.' + suite + ".suite_setup"
try:
module = my_import(module_name)
except Exception, e:
report_fail("load suite [" + suite +"] fail: " + str(e))
self.load_fails = self.load_fails +1
return False
try:
suite_instance = module.CTestSuite(suite, \
self.root_path + '/suites/' + suite, running_folder)
except Exception, e:
report_fail("initialize suite fail: " + str(e))
self.load_fails = self.load_fails +1
return False
result, message = suite_instance.load_settings()
if not result:
report_fail("load settings fail: " + str(e))
self.load_fails = self.load_fails +1
return False
try:
result, message = suite_instance.on_suite_setup()
except Exception, e:
result = False
message = str(e);
if not result:
api_log_error(message)
report_fail (message)
self.setup_fails = self.setup_fails + 1
return False
self.running_suite = suite
cases.sort()
# run cases
for case in cases:
if not os.path.isdir(self.root_path + '/suites/' + suite + '/cases/' + case):
continue
self.running_case = case
self.run_case(suite_instance, case)
self.running_case = ''
# suites cleanup
self.running_suite = ''
try:
result, message = suite_instance.on_suite_cleanup()
except Exception, e:
result = False
message = str(e);
if not result:
api_log_error(message)
report_fail (message)
self.setup_fails = self.setup_fails + 1
return
def start_run(self):
if self.target_suites is None:
print "\n\nstart run: no target suites, exit.."
return
cur_time = time.localtime()
time_prefix = "{:02}-{:02}-{:02}-{:02}".format(
cur_time.tm_mon, cur_time.tm_mday, cur_time.tm_hour, cur_time.tm_min)
debug = api_get_value('debug', False)
if debug:
self.running_folder = 'debug'
else:
self.running_folder = 'run-' + time_prefix
folder = self.root_path + "/run/" +self.running_folder;
if os.path.exists(folder):
shutil.rmtree(folder, ignore_errors=True)
if not os.path.exists(folder):
os.makedirs(folder )
os.makedirs(folder + "/suites")
api_init_log(folder + "/test.log")
self.report = open(folder + "/report.txt", 'a')
self.target_suites.sort()
for suite in self.target_suites:
if not os.path.isdir(self.root_path + '/suites/' + suite):
continue
self.report.write("suite " + suite + " cases:\n")
if self.target_cases is None:
cases = os.listdir(self.root_path + "/suites/" + suite + "/cases")
self.run_suite(suite, cases)
else:
self.run_suite(suite, self.target_cases)
self.report.write("\n")
self.report.write("\n\n")
summary = self.gen_execution_stats()
self.report.write(summary);
self.report.flush()
self.report.close()
print summary
def report_fail(message, case_description=''):
global framework
if framework is not None:
framework.report_result(False, message, case_description)
api_log_error(message)
return
def report_success(case_description=''):
global framework
if framework is not None:
framework.report_result(True , "OK", case_description)
return

View File

@ -0,0 +1,40 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import os
import json
class CTestSuiteBase(object):
def __init__(self, name, suite_path, run_path):
self.suite_path=suite_path
self.run_path=run_path
self.m_name = name
self.settings = {}
def get_settings_item(self, item):
if item in self.settings:
return self.settings[item]
else:
return None
def load_settings(self):
path = self.suite_path + "/settings.cfg"
if os.path.isfile(path):
try:
fp = open(path, 'r')
self.settings = json.load(fp)
fp.close()
except Exception, e:
return False, 'Load settings fail: ' + e.message
return True, 'OK'
else:
return True, 'No file'
def on_suite_setup(self):
return True, 'OK'
def on_suite_cleanup(self):
return True, 'OK'

View File

@ -0,0 +1,98 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import logging
import threading
from .test_utils import *
global logger
logger = None
def api_init_log(log_path):
global logger
print "api_init_log: " + log_path
logger = logging.getLogger(__name__)
logger.setLevel(level = logging.INFO)
handler = logging.FileHandler(log_path)
handler.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
console = logging.StreamHandler()
console.setLevel(logging.INFO)
logger.addHandler(handler)
logger.addHandler(console)
return
def api_log(message):
global logger
if logger is None:
print message
else:
logger.info (message)
return
def api_log_error(message):
global logger
if logger is None:
print message
else:
logger.error (message)
return
def api_logv(message):
global logger
if logger is None:
print message
else:
logger.info(message)
return
#####################################3
global g_case_runner_event
def api_wait_case_event(timeout):
global g_case_runner_event
g_case_runner_event.clear()
g_case_runner_event.wait(timeout)
def api_notify_case_runner():
global g_case_runner_event
g_case_runner_event.set()
def api_create_case_event():
global g_case_runner_event
g_case_runner_event = threading.Event()
#######################################
def api_init_globals():
global _global_dict
_global_dict = {}
def api_set_value(name, value):
_global_dict[name] = value
def api_get_value(name, defValue=None):
try:
return _global_dict[name]
except KeyError:
return defValue
#########################################
global root_path
def api_set_root_path(root):
global root_path
root_path = root
def api_get_root_path():
global root_path
return root_path;

View File

@ -0,0 +1,70 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import datetime
import os
import random
import re
import shlex
import subprocess
import sys
import time
import shutil
from subprocess import check_output, CalledProcessError
def t_getPIDs(process):
try:
pidlist = map(int, check_output(["pidof", process]).split())
except CalledProcessError:
pidlist = []
#print process + ':list of PIDs = ' + ', '.join(str(e) for e in pidlist)
return pidlist
def t_kill_process_by_name(p_keywords):
pid_list = []
ps_info = subprocess.check_output(shlex.split("ps aux")).split("\n")
for p in ps_info:
if p_keywords in p:
tmp = p.split(" ")
tmp = [x for x in tmp if len(x) > 0]
pid_list.append(tmp[1])
for pid in pid_list:
cmd = "kill -9 {}".format(pid)
subprocess.call(shlex.split(cmd))
return pid_list
#proc -> name of the process
#kill = 1 -> search for pid for kill
#kill = 0 -> search for name (default)
def t_process_exists(proc, kill = 0):
ret = False
processes = t_getPIDs(proc)
for pid in processes:
if kill == 0:
return True
else:
print "kill [" + proc + "], pid=" + str(pid)
os.kill((pid), 9)
ret = True
return ret
def t_copy_files(source_dir, pattern, dest_dir):
files = os.listdir(source_dir)
for file in files:
if file is '/' or file is '.' or file is '..':
continue
if pattern == '*' or pattern is '' or files.endswith(pattern):
shutil.copy(source_dir+"/"+ file,dest_dir)

View File

@ -0,0 +1,150 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import os
import shutil
import subprocess
import json
import time
from framework import test_api
from framework.test_utils import *
output = "output.txt"
def start_env():
os.system("./start.sh")
def stop_env():
os.system("./stop.sh")
time.sleep(0.5)
os.chdir("../") #reset path for other cases in the same suite
def check_is_timeout():
line_num = 0
ft = open(output, 'r')
lines = ft.readlines()
for line in reversed(lines):
if (line[0:36] == "--------one operation begin.--------"):
break
line_num = line_num + 1
ft.close()
if (lines[-(line_num)] == "operation timeout"):
return True
else:
return False
def parse_ret(file):
ft = open(file, 'a')
ft.writelines("\n")
ft.writelines("--------one operation finish.--------")
ft.writelines("\n")
ft.close()
ft = open(file, 'r')
for line in reversed(ft.readlines()):
if (line[0:16] == "response status "):
ret = line[16:]
ft.close()
return int(ret)
def run_host_tool(cmd, file):
ft = open(file, 'a')
ft.writelines("--------one operation begin.--------")
ft.writelines("\n")
ft.close()
os.system(cmd + " -o" + file)
if (check_is_timeout() == True):
return -1
return parse_ret(file)
def install_app(app_name, file_name):
return run_host_tool("./host_tool -i " + app_name + " -f ../test-app/" + file_name, output)
def uninstall_app(app_name):
return run_host_tool("./host_tool -u " + app_name, output)
def query_app():
return run_host_tool("./host_tool -q ", output)
def send_request(url, action, payload):
if (payload is None):
return run_host_tool("./host_tool -r " + url + " -A " + action, output)
else:
return run_host_tool("./host_tool -r " + url + " -A " + action + " -p " + payload, output)
def register(url, timeout, alive_time):
return run_host_tool("./host_tool -s " + url + " -t " + str(timeout) + " -a " + str(alive_time), output)
def deregister(url):
return run_host_tool("./host_tool -d " + url, output)
def get_response_payload():
line_num = 0
ft = open(output, 'r')
lines = ft.readlines()
for line in reversed(lines):
if (line[0:16] == "response status "):
break
line_num = line_num + 1
payload_lines = lines[-(line_num):-1]
ft.close()
return payload_lines
def check_query_apps(expected_app_list):
if (check_is_timeout() == True):
return False
json_lines = get_response_payload()
json_str = " ".join(json_lines)
json_dict = json.loads(json_str)
app_list = []
for key, value in json_dict.items():
if key[0:6] == "applet":
app_list.append(value)
if (sorted(app_list) == sorted(expected_app_list)):
return True
else:
return False
def check_response_payload(expected_payload):
if (check_is_timeout() == True):
return False
json_lines = get_response_payload()
json_str = " ".join(json_lines)
if (json_str.strip() != ""):
json_dict = json.loads(json_str)
else:
json_dict = {}
if (json_dict == expected_payload):
return True
else:
return False
def check_get_event():
line_num = 0
ft = open(output, 'r')
lines = ft.readlines()
for line in reversed(lines):
if (line[0:16] == "response status "):
break
line_num = line_num + 1
payload_lines = lines[-(line_num):-1]
ft.close()
if (payload_lines[1][0:17] == "received an event"):
return True
else:
return False

View File

@ -0,0 +1,285 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include "host_api.h"
#include "bi-inc/attr_container.h"
#include "er-coap-constants.h"
static char *read_file_to_buffer(const char *filename, int *ret_size);
int send_request_to_applet_success = 0;
const char *label_for_request = "request1";
int event_listener_counter = 0;
char *applet_buf[1024 * 1024];
const char *host_agent_ip = "127.0.0.1";
void f_aee_response_handler(void *usr_ctx, aee_response_t *response)
{
if (response == NULL) {
printf("########## request timeout!!! \n");
} else {
char *str = (char *) usr_ctx;
printf("#### dump response ####\n");
printf("#### user data: %s \n", str);
printf("#### status: %d \n", response->status);
if (response->payload != NULL)
attr_container_dump((attr_container_t *) response->payload);
}
}
void f_aee_event_listener(const char *url, void *event, int fmt)
{
printf("######## event is received. url: %s, fmt:%d ############\n", url,
fmt);
attr_container_t *attr_obj = (attr_container_t *) event;
attr_container_dump(attr_obj);
/*
if (0 == strcmp(url, "alert/overheat"))
{
event_listener_counter++;
printf("event :%d \n", event_listener_counter);
}
*/
}
static int print_menu_and_select(void)
{
char s[256];
int choice;
do {
printf("\n");
printf("1. Install TestApplet1\n");
printf("2. Install TestApplet2\n");
printf("3. Install TestApplet3\n");
printf("4. Uninstall TestApplet1\n");
printf("5. Uninstall TestApplet2\n");
printf("6. Uninstall TestApplet3\n");
printf("7. Send Request to TestApplet1\n");
printf("8. Register Event to TestApplet1\n");
printf("9. UnRegister Event to TestApplet1\n");
printf("a. Query Applets\n");
printf("t. Auto Test\n");
printf("q. Exit\n");
printf("Please Select: ");
if (fgets(s, sizeof(s), stdin)) {
if (!strncmp(s, "q", 1))
return 0;
if (!strncmp(s, "a", 1))
return 10;
if (!strncmp(s, "t", 1))
return 20;
choice = atoi(s);
if (choice >= 1 && choice <= 9)
return choice;
}
} while (1);
return 0;
}
static void install_applet(int index)
{
char applet_name[64];
char applet_file_name[64];
char *buf;
int size;
int ret;
printf("Installing TestApplet%d...\n", index);
snprintf(applet_name, sizeof(applet_name), "TestApplet%d", index);
snprintf(applet_file_name, sizeof(applet_file_name), "./TestApplet%d.wasm",
index);
buf = read_file_to_buffer(applet_file_name, &size);
if (!buf) {
printf("Install Applet failed: read file %s error.\n",
applet_file_name);
return;
}
//step2. install applet
ret = aee_applet_install(buf, "wasm", size, applet_name, 5000);
if (ret) {
printf("%s install success\n", applet_name);
}
free(buf);
}
static void uninstall_applet(int index)
{
int ret;
char applet_name[64];
snprintf(applet_name, sizeof(applet_name), "TestApplet%d", index);
ret = aee_applet_uninstall(applet_name, "wasm", 5000);
if (ret) {
printf("uninstall %s success\n", applet_name);
} else {
printf("uninstall %s failed\n", applet_name);
}
}
static void send_request(int index)
{
char url[64];
int ret;
aee_request_t req;
const char *user_context = "label for request";
attr_container_t *attr_obj = attr_container_create(
"Send Request to Applet");
attr_container_set_string(&attr_obj, "String key", "Hello");
attr_container_set_int(&attr_obj, "Int key", 1000);
attr_container_set_int64(&attr_obj, "Int64 key", 0x77BBCCDD11223344LL);
//specify the target wasm app
snprintf(url, sizeof(url), "/app/TestApplet%d/url1", index);
//not specify the target wasm app
//snprintf(url, sizeof(url), "url1");
aee_request_init(&req, url, COAP_PUT);
aee_request_set_payload(&req, attr_obj,
attr_container_get_serialize_length(attr_obj),
PAYLOAD_FORMAT_ATTRIBUTE_OBJECT);
ret = aee_request_send(&req, f_aee_response_handler, (void *) user_context,
10000);
if (ret) {
printf("send request to TestApplet1 success\n");
}
}
static void register_event(const char *event_path)
{
hostclient_register_event(event_path, f_aee_event_listener);
}
static void unregister_event(const char *event_path)
{
hostclient_unregister_event(event_path);
}
static void query_applets()
{
aee_applet_list_t applet_lst;
aee_applet_list_init(&applet_lst);
aee_applet_list(5000, &applet_lst);
aee_applet_list_clean(&applet_lst);
}
static char *
read_file_to_buffer(const char *filename, int *ret_size)
{
FILE *fl = NULL;
char *buffer = NULL;
int file_size = 0;
if (!(fl = fopen(filename, "rb"))) {
printf("file open failed\n");
return NULL;
}
fseek(fl, 0, SEEK_END);
file_size = ftell(fl);
if (file_size == 0) {
printf("file length 0\n");
return NULL;
}
if (!(buffer = (char *) malloc(file_size))) {
fclose(fl);
return NULL;
}
fseek(fl, 0, SEEK_SET);
if (!fread(buffer, 1, file_size, fl)) {
printf("file read failed\n");
return NULL;
}
fclose(fl);
*ret_size = file_size;
return buffer;
}
static void auto_test()
{
int i;
int interval = 1000; /* ms */
while (1) {
uninstall_applet(1);
uninstall_applet(2);
uninstall_applet(3);
install_applet(1);
install_applet(2);
install_applet(3);
for (i = 0; i < 60 * 1000 / interval; i++) {
query_applets();
send_request(1);
send_request(2);
send_request(3);
usleep(interval * 1000);
}
}
}
void exit_program()
{
hostclient_shutdown();
exit(0);
}
int
main()
{
bool ret;
//step1. host client init
ret = hostclient_initialize(host_agent_ip, 3456);
if (!ret) {
printf("host client initialize failed\n");
return -1;
}
do {
int choice = print_menu_and_select();
printf("\n");
if (choice == 0)
exit_program();
if (choice <= 3)
install_applet(choice);
else if (choice <= 6)
uninstall_applet(choice - 3);
else if (choice <= 7)
send_request(1);
else if (choice <= 8)
register_event("alert/overheat");
else if (choice <= 9)
unregister_event("alert/overheat");
else if (choice == 10)
query_applets();
else if (choice == 20)
auto_test();
} while (1);
return 0;
}
// Run program: Ctrl + F5 or Debug > Start Without Debugging menu
// Debug program: F5 or Debug > Start Debugging menu
// Tips for Getting Started:
// 1. Use the Solution Explorer window to add/manage files
// 2. Use the Team Explorer window to connect to source control
// 3. Use the Output window to see build output and other messages
// 4. Use the Error List window to view errors
// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project
// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file

View File

@ -0,0 +1,44 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
CC = gcc
CFLAGS := -Wall -g
# Add this to make compiler happy
CFLAGS += -DWASM_ENABLE_INTERP=1
host_api_c=../../../../host-agent/host-api-c
attr_container_dir=../../../../wamr/core/app-framework/app-native-shared
coap_dir=../../../../host-agent/coap
shared_dir=../../../../wamr/core/shared
# core
INCLUDE_PATH = -I$(host_api_c)/src -I$(attr_container_dir)/ \
-I$(coap_dir)/er-coap -I$(coap_dir)/er-coap/extension \
-I$(shared_dir)/include \
-I$(shared_dir)/utils \
-I$(shared_dir)/platform/include/ \
-I$(shared_dir)/platform/linux/
LIB := $(host_api_c)/src/libhostapi.a
EXE := ./hostapp
App_C_Files := host_app_sample.c
OBJS := $(App_C_Files:.c=.o)
all: $(EXE)
%.o: %.c
@$(CC) $(CFLAGS) -c $< -o $@ $(INCLUDE_PATH)
$(EXE): $(OBJS)
@rm -f $(EXE)
@$(CC) $(OBJS) -o $(EXE) $(LIB) -lpthread -lrt
@rm -f $(OBJS)
.PHONY: clean
clean:
rm -f $(OBJS) $(EXE)

View File

@ -0,0 +1,7 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#!/bin/sh

View File

@ -0,0 +1,151 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
It is the entrance of the iagent test framework.
"""
import argparse
import datetime
import os
import pprint
import random
import re
import shlex
import subprocess
import signal
import sys
import time
sys.path.append('../../../app-sdk/python')
from framework.test_utils import *
from framework.framework import *
def signal_handler(signal, frame):
print('Pressed Ctrl+C!')
sys.exit(0)
def Register_signal_handler():
signal.signal(signal.SIGINT, signal_handler)
# signal.pause()
def flatten_args_list(l):
if l is None:
return None
return [x for y in l for x in y]
if __name__ == "__main__":
parser = argparse.ArgumentParser(description = "to run specific case(s) "\
"in specific suite(s) with FC test framework")
parser.add_argument('-s', dest = 'suite_id', action = 'append',
nargs = '+',
help = 'one or multiple suite ids, which are also setup ids.'\
'by default if it isn\'t passed from argument, all '\
'suites are going to be run.')
parser.add_argument('-t', dest = 'case_id', action = 'append',
nargs = '+',
help = 'one or multiple cases ids.'\
'by default if it isn\'t passed from argument, all '\
'cases in specific suites are going to be run.')
parser.add_argument('-n', dest = 'repeat_time', action = 'store',
default = 1,
help = 'how many times do you want to run. there is 40s '\
'break time between two rounds. each round includs '\
'init_setup, run_test_case and deinit_setup.')
parser.add_argument('--shuffle_all', dest = 'shuffle_all',
default = False, action = 'store_true',
help = 'shuffle_all test cases in per test suite '\
'by default, all cases under per suite should '\
'be executed by input order.')
parser.add_argument('--cases_list', dest='cases_list_file_path',
default=None,
action='store',
help="read cases list from a flie ")
parser.add_argument('--skip_proc', dest='skip_proc',
default = False, action = 'store_true',
help='do not start the test process.'\
'sometimes the gw_broker process will be started in eclipse for debug purpose')
parser.add_argument('-b', dest = 'binaries', action = 'store',
help = 'The path of target folder ')
parser.add_argument('-d', dest = 'debug', action = 'store_true',
help = 'wait user to attach the target process after launch processes ')
parser.add_argument('--rebuild', dest = 'rebuild', action = 'store_true',
help = 'rebuild all test binaries')
args = parser.parse_args()
print "------------------------------------------------------------"
print "parsing arguments ... ..."
print args
'''
logger = logging.getLogger('coapthon.server.coap')
logger.setLevel(logging.DEBUG)
console = logging.StreamHandler()
console.setLevel(logging.DEBUG)
logger.addHandler(console)
'''
print "------------------------------------------------------------"
print "preparing wamr binary and test tools ... ..."
os.system("cd ../../samples/simple/ && bash build.sh -p host-interp")
Register_signal_handler()
api_init_globals();
api_create_case_event();
suites_list = flatten_args_list(args.suite_id)
cases_list = flatten_args_list(args.case_id)
dirname, filename = os.path.split(os.path.abspath(sys.argv[0]))
api_set_root_path(dirname);
framework = CTestFramework(dirname);
framework.repeat_time = int(args.repeat_time)
framework.shuffle_all = args.shuffle_all
framework.skip_proc=args.skip_proc
api_set_value('keep_env', args.skip_proc)
api_set_value('debug', args.debug)
api_set_value('rebuild', args.rebuild)
binary_path = args.binaries
if binary_path is None:
binary_path = os.path.abspath(dirname + '/../..')
print "checking execution binary path: " + binary_path
if not os.path.exists(binary_path):
print "The execution binary path was not available. quit..."
os._exit(0)
api_set_value('binary_path', binary_path)
if suites_list is not None:
framework.target_suites = suites_list
else:
framework.load_suites()
framework.target_cases = cases_list
framework.start_run()
print "\n\n------------------------------------------------------------"
print "The run folder is [" + framework.running_folder +"]"
print "that's all. bye"
print "kill to quit.."
t_kill_process_by_name("start.py")
sys.exit(0)
os._exit()

View File

@ -0,0 +1,94 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import sys
import time
import random
import logging
import json
from framework.case_base import *
from framework.test_api import *
from harness.harness_api import *
class CTestCase(CTestCaseBase):
def __init__(self, suite):
CTestCaseBase.__init__(self, suite)
def get_case_name(self):
case_path = os.path.dirname(os.path.abspath( __file__ ))
return os.path.split(case_path)[1]
def on_get_case_description(self):
return "startup the executables"
def on_setup_case(self):
os.chdir(self.get_case_name())
start_env()
api_log_error("on_setup_case OK")
return True, ''
def on_cleanup_case(self):
stop_env()
api_log_error("on_cleanup_case OK")
return True, ''
# called by the framework
def on_run_case(self):
time.sleep(0.5)
#uninstall inexistent App1
ret = uninstall_app("App1")
if (ret != 160):
return False, ''
#query Apps
ret = query_app()
if (ret != 69):
return False, ''
ret = check_query_apps([])
if (ret == False):
return False, ''
#install App1
ret = install_app("App1", "01_install.wasm")
if (ret != 65):
return False, ''
#query Apps
ret = query_app()
if (ret != 69):
return False, ''
ret = check_query_apps(["App1"])
if (ret == False):
return False, ''
#install App2
ret = install_app("App2", "01_install.wasm")
if (ret != 65):
return False, ''
#query Apps
ret = query_app()
if (ret != 69):
return False, ''
ret = check_query_apps(["App1","App2"])
if (ret == False):
return False, ''
#uninstall App2
ret = uninstall_app("App2")
if (ret != 66):
return False, ''
#query Apps
ret = query_app()
if (ret != 69):
return False, ''
ret = check_query_apps(["App1"])
if (ret == False):
return False, ''
return True, ''

View File

@ -0,0 +1,73 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import sys
import time
import random
import logging
import json
from framework.case_base import *
from framework.test_api import *
from harness.harness_api import *
class CTestCase(CTestCaseBase):
def __init__(self, suite):
CTestCaseBase.__init__(self, suite)
def get_case_name(self):
case_path = os.path.dirname(os.path.abspath( __file__ ))
return os.path.split(case_path)[1]
def on_get_case_description(self):
return "startup the executables"
def on_setup_case(self):
os.chdir(self.get_case_name())
start_env()
api_log_error("on_setup_case OK")
return True, ''
def on_cleanup_case(self):
stop_env()
api_log_error("on_cleanup_case OK")
return True, ''
# called by the framework
def on_run_case(self):
time.sleep(0.5)
#install App1
ret = install_app("App1", "02_request.wasm")
if (ret != 65):
return False, ''
#query Apps
ret = query_app()
if (ret != 69):
return False, ''
ret = check_query_apps(["App1"])
if (ret == False):
return False, ''
#send request to App1
ret = send_request("/res1", "GET", None)
if (ret != 69):
return False, ''
expect_response_payload = {"key1":"value1","key2":"value2"}
ret = check_response_payload(expect_response_payload)
if (ret == False):
return False, ''
#send request to App1
ret = send_request("/res2", "DELETE", None)
if (ret != 66):
return False, ''
expect_response_payload = {}
ret = check_response_payload(expect_response_payload)
if (ret == False):
return False, ''
return True, ''

View File

@ -0,0 +1,67 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import sys
import time
import random
import logging
import json
from framework.case_base import *
from framework.test_api import *
from harness.harness_api import *
class CTestCase(CTestCaseBase):
def __init__(self, suite):
CTestCaseBase.__init__(self, suite)
def get_case_name(self):
case_path = os.path.dirname(os.path.abspath( __file__ ))
return os.path.split(case_path)[1]
def on_get_case_description(self):
return "startup the executables"
def on_setup_case(self):
os.chdir(self.get_case_name())
start_env()
api_log_error("on_setup_case OK")
return True, ''
def on_cleanup_case(self):
stop_env()
api_log_error("on_cleanup_case OK")
return True, ''
# called by the framework
def on_run_case(self):
time.sleep(0.5)
#install App1
ret = install_app("App1", "03_event.wasm")
if (ret != 65):
return False, ''
#query Apps
ret = query_app()
if (ret != 69):
return False, ''
ret = check_query_apps(["App1"])
if (ret == False):
return False, ''
#register event
ret = register("/alert/overheat", 2000, 5000)
if (ret != 69):
return False, ''
ret = check_get_event()
if (ret == False):
return False, ''
#deregister event
ret = deregister("/alert/overheat")
if (ret != 69):
return False, ''
return True, ''

View File

@ -0,0 +1,80 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import sys
import time
import random
import logging
import json
from framework.case_base import *
from framework.test_api import *
from harness.harness_api import *
class CTestCase(CTestCaseBase):
def __init__(self, suite):
CTestCaseBase.__init__(self, suite)
def get_case_name(self):
case_path = os.path.dirname(os.path.abspath( __file__ ))
return os.path.split(case_path)[1]
def on_get_case_description(self):
return "startup the executables"
def on_setup_case(self):
os.chdir(self.get_case_name())
start_env()
api_log_error("on_setup_case OK")
return True, ''
def on_cleanup_case(self):
stop_env()
api_log_error("on_cleanup_case OK")
return True, ''
# called by the framework
def on_run_case(self):
time.sleep(0.5)
#install App1
ret = install_app("App1", "04_request_internal_resp.wasm")
if (ret != 65):
return False, ''
#install App2
ret = install_app("App2", "04_request_internal_req.wasm")
if (ret != 65):
return False, ''
#query Apps
ret = query_app()
if (ret != 69):
return False, ''
ret = check_query_apps(["App1","App2"])
if (ret == False):
return False, ''
#send request to App2
ret = send_request("/res1", "GET", None)
if (ret != 69):
return False, ''
time.sleep(2)
expect_response_payload = {"key1":"value1","key2":"value2"}
ret = check_response_payload(expect_response_payload)
if (ret == False):
return False, ''
#send request to App2
ret = send_request("/res2", "GET", None)
if (ret != 69):
return False, ''
time.sleep(2)
expect_response_payload = {"key1":"value1","key2":"value2"}
ret = check_response_payload(expect_response_payload)
if (ret == False):
return False, ''
return True, ''

View File

@ -0,0 +1,70 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import sys
import time
import random
import logging
import json
from framework.case_base import *
from framework.test_api import *
from harness.harness_api import *
class CTestCase(CTestCaseBase):
def __init__(self, suite):
CTestCaseBase.__init__(self, suite)
def get_case_name(self):
case_path = os.path.dirname(os.path.abspath( __file__ ))
return os.path.split(case_path)[1]
def on_get_case_description(self):
return "startup the executables"
def on_setup_case(self):
os.chdir(self.get_case_name())
start_env()
api_log_error("on_setup_case OK")
return True, ''
def on_cleanup_case(self):
stop_env()
api_log_error("on_cleanup_case OK")
return True, ''
# called by the framework
def on_run_case(self):
time.sleep(0.5)
#install App1
ret = install_app("App1", "05_event_internal_provider.wasm")
if (ret != 65):
return False, ''
#install App2
ret = install_app("App2", "05_event_internal_subscriber.wasm")
if (ret != 65):
return False, ''
#query Apps
ret = query_app()
if (ret != 69):
return False, ''
ret = check_query_apps(["App1","App2"])
if (ret == False):
return False, ''
#send request to App2
ret = send_request("/res1", "GET", None)
if (ret != 69):
return False, ''
time.sleep(2)
expect_response_payload = {"key1":"value1","key2":"value2"}
ret = check_response_payload(expect_response_payload)
if (ret == False):
return False, ''
return True, ''

View File

@ -0,0 +1,70 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import sys
import time
import random
import logging
import json
from framework.case_base import *
from framework.test_api import *
from harness.harness_api import *
class CTestCase(CTestCaseBase):
def __init__(self, suite):
CTestCaseBase.__init__(self, suite)
def get_case_name(self):
case_path = os.path.dirname(os.path.abspath( __file__ ))
return os.path.split(case_path)[1]
def on_get_case_description(self):
return "startup the executables"
def on_setup_case(self):
os.chdir(self.get_case_name())
start_env()
api_log_error("on_setup_case OK")
return True, ''
def on_cleanup_case(self):
stop_env()
api_log_error("on_cleanup_case OK")
return True, ''
# called by the framework
def on_run_case(self):
time.sleep(0.5)
#install App1
ret = install_app("App1", "06_timer.wasm")
if (ret != 65):
return False, ''
#query Apps
ret = query_app()
if (ret != 69):
return False, ''
ret = check_query_apps(["App1"])
if (ret == False):
return False, ''
#send request to App1
ret = send_request("/res1", "GET", None)
if (ret != 69):
return False, ''
time.sleep(3)
ret = send_request("/check_timer", "GET", None)
if (ret != 69):
return False, ''
expect_response_payload = {"num":2}
ret = check_response_payload(expect_response_payload)
if (ret == False):
return False, ''
return True, ''

View File

@ -0,0 +1,65 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import sys
import time
import random
import logging
import json
from framework.case_base import *
from framework.test_api import *
from harness.harness_api import *
class CTestCase(CTestCaseBase):
def __init__(self, suite):
CTestCaseBase.__init__(self, suite)
def get_case_name(self):
case_path = os.path.dirname(os.path.abspath( __file__ ))
return os.path.split(case_path)[1]
def on_get_case_description(self):
return "startup the executables"
def on_setup_case(self):
os.chdir(self.get_case_name())
start_env()
api_log_error("on_setup_case OK")
return True, ''
def on_cleanup_case(self):
stop_env()
api_log_error("on_cleanup_case OK")
return True, ''
# called by the framework
def on_run_case(self):
time.sleep(0.5)
#install App1
ret = install_app("App1", "07_sensor.wasm")
if (ret != 65):
return False, ''
#query Apps
ret = query_app()
if (ret != 69):
return False, ''
ret = check_query_apps(["App1"])
if (ret == False):
return False, ''
#send request to App1
ret = send_request("/res1", "GET", None)
if (ret != 69):
return False, ''
time.sleep(2)
expect_response_payload = {"key1":"value1","key2":"value2"}
ret = check_response_payload(expect_response_payload)
if (ret == False):
return False, ''
return True, ''

View File

@ -0,0 +1,78 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import sys
import time
import random
import logging
import json
from framework.case_base import *
from framework.test_api import *
from harness.harness_api import *
class CTestCase(CTestCaseBase):
def __init__(self, suite):
CTestCaseBase.__init__(self, suite)
def get_case_name(self):
case_path = os.path.dirname(os.path.abspath( __file__ ))
return os.path.split(case_path)[1]
def on_get_case_description(self):
return "startup the executables"
def on_setup_case(self):
os.chdir(self.get_case_name())
start_env()
api_log_error("on_setup_case OK")
return True, ''
def on_cleanup_case(self):
stop_env()
api_log_error("on_cleanup_case OK")
return True, ''
# called by the framework
def on_run_case(self):
time.sleep(0.5)
#install App1
ret = install_app("App1", "08_on_destroy.wasm")
if (ret != 65):
return False, ''
#query Apps
ret = query_app()
if (ret != 69):
return False, ''
ret = check_query_apps(["App1"])
if (ret == False):
return False, ''
#send request to App1
ret = send_request("/res1", "GET", None)
if (ret != 69):
return False, ''
time.sleep(2)
expect_response_payload = {"key1":"value1"}
ret = check_response_payload(expect_response_payload)
if (ret == False):
return False, ''
#uninstall App1
ret = uninstall_app("App1")
if (ret != 66):
return False, ''
#query Apps
ret = query_app()
if (ret != 69):
return False, ''
ret = check_query_apps([])
if (ret == False):
return False, ''
return True, ''

View File

@ -0,0 +1,56 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import os
import shutil
import types
import time
import glob
from framework.test_api import *
from framework.test_utils import *
from harness.harness_api import *
from framework.suite import *
class CTestSuite(CTestSuiteBase):
setup_path = ""
def __init__(self, name, suite_path, run_path):
CTestSuiteBase.__init__(self, name, suite_path, run_path)
def on_suite_setup(self):
global setup_path
setup_path = os.getcwd()
cases = os.listdir(self.suite_path + "/cases/")
cases.sort()
if api_get_value("rebuild", False):
path_tmp = os.getcwd()
os.chdir(self.suite_path + "/test-app")
os.system(self.suite_path + "/test-app" + "/build.sh")
os.chdir(path_tmp)
os.makedirs(self.run_path + "/test-app")
for case in cases:
if case != "__init__.pyc" and case != "__init__.py":
os.makedirs(self.run_path + "/" + case)
#copy each case's host_tool, simple, wasm files, start/stop scripts to the run directory,
shutil.copy(setup_path + "/../../samples/simple/out/simple", self.run_path + "/" + case)
shutil.copy(setup_path + "/../../samples/simple/out/host_tool", self.run_path + "/" + case)
for file in glob.glob(self.suite_path + "/test-app/" + "/*.wasm"):
shutil.copy(file, self.run_path + "/test-app")
shutil.copy(self.suite_path + "/tools/product/start.sh", self.run_path + "/" + case)
shutil.copy(self.suite_path + "/tools/product/stop.sh", self.run_path + "/" + case)
os.chdir(self.run_path)
return True, 'OK'
def on_suite_cleanup(self):
global setup_path
os.chdir(setup_path)
api_log("stopping env..")
return True, 'OK'

View File

@ -0,0 +1,16 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wasm_app.h"
void on_init()
{
printf("Hello, I was installed.\n");
}
void on_destroy()
{
/* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
}

View File

@ -0,0 +1,62 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wasm_app.h"
#include "wa-inc/request.h"
void res1_handler(request_t *request)
{
response_t response[1];
attr_container_t *payload;
printf("### user resource 1 handler called\n");
printf("###### dump request ######\n");
printf("sender: %lu\n", request->sender);
printf("url: %s\n", request->url);
printf("action: %d\n", request->action);
printf("payload:\n");
if (request->payload
!= NULL&& request->payload_len > 0 && request->fmt == FMT_ATTR_CONTAINER)
attr_container_dump((attr_container_t *) request->payload);
printf("#### dump request end ###\n");
payload = attr_container_create("wasm app response payload");
if (payload == NULL)
return;
attr_container_set_string(&payload, "key1", "value1");
attr_container_set_string(&payload, "key2", "value2");
make_response_for_request(request, response);
set_response(response, CONTENT_2_05,
FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload));
printf("reciver: %lu, mid:%d\n", response->reciever, response->mid);
api_response_send(response);
attr_container_destroy(payload);
}
void res2_handler(request_t *request)
{
response_t response[1];
make_response_for_request(request, response);
set_response(response, DELETED_2_02, 0, NULL, 0);
api_response_send(response);
printf("### user resource 2 handler called\n");
}
void on_init()
{
/* register resource uri */
api_register_resource_handler("/res1", res1_handler);
api_register_resource_handler("/res2", res2_handler);
}
void on_destroy()
{
/* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wasm_app.h"
#include "wa-inc/timer_wasm_app.h"
#include "wa-inc/request.h"
int num = 0;
void publish_overheat_event()
{
attr_container_t *event;
event = attr_container_create("event");
attr_container_set_string(&event, "warning", "temperature is over high");
printf("###app publish event begin ###\n");
api_publish_event("alert/overheat", FMT_ATTR_CONTAINER, event,
attr_container_get_serialize_length(event));
printf("###app publish event end ###\n");
attr_container_destroy(event);
}
/* Timer callback */
void timer1_update(user_timer_t timer)
{
printf("Timer update %d\n", num++);
publish_overheat_event();
}
void start_timer()
{
user_timer_t timer;
/* set up a timer */
timer = api_timer_create(1000, true, false, timer1_update);
api_timer_restart(timer, 1000);
}
void on_init()
{
start_timer();
}
void on_destroy()
{
/* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wasm_app.h"
#include "wa-inc/request.h"
uint32 mid;
unsigned long sender;
void my_response_handler(response_t *response, void *user_data)
{
attr_container_t *payload;
printf("### user resource 1 handler called\n");
payload = attr_container_create("wasm app response payload");
if (payload == NULL)
return;
attr_container_set_string(&payload, "key1", "value1");
attr_container_set_string(&payload, "key2", "value2");
response->mid = mid;
response->reciever = sender;
set_response(response, CONTENT_2_05,
FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload));
printf("reciver: %lu, mid:%d\n", response->reciever, response->mid);
api_response_send(response);
attr_container_destroy(payload);
}
static void test_send_request(const char *url, const char *tag)
{
request_t request[1];
init_request(request, (char *)url, COAP_PUT, 0, NULL, 0);
api_send_request(request, my_response_handler, (void *)tag);
}
void res1_handler(request_t *request)
{
mid = request->mid;
sender = request->sender;
test_send_request("url1", "a general request");
}
void res2_handler(request_t *request)
{
mid = request->mid;
sender = request->sender;
test_send_request("/app/App1/url1", "a general request");
}
void on_init()
{
/* register resource uri */
api_register_resource_handler("/res1", res1_handler);
api_register_resource_handler("/res2", res2_handler);
}
void on_destroy()
{
/* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wasm_app.h"
#include "wa-inc/request.h"
void res1_handler(request_t *request)
{
response_t response[1];
attr_container_t *payload;
printf("[resp] ### user resource 1 handler called\n");
printf("[resp] ###### dump request ######\n");
printf("[resp] sender: %lu\n", request->sender);
printf("[resp] url: %s\n", request->url);
printf("[resp] action: %d\n", request->action);
printf("[resp] payload:\n");
if (request->payload != NULL && request->fmt == FMT_ATTR_CONTAINER)
attr_container_dump((attr_container_t *) request->payload);
printf("[resp] #### dump request end ###\n");
payload = attr_container_create("wasm app response payload");
if (payload == NULL)
return;
attr_container_set_string(&payload, "key1", "value1");
attr_container_set_string(&payload, "key2", "value2");
make_response_for_request(request, response);
set_response(response, CONTENT_2_05,
FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload));
printf("[resp] response payload len %d\n",
attr_container_get_serialize_length(payload));
printf("[resp] reciver: %lu, mid:%d\n", response->reciever, response->mid);
api_response_send(response);
attr_container_destroy(payload);
}
void on_init()
{
/* register resource uri */
api_register_resource_handler("/url1", res1_handler);
}
void on_destroy()
{
/* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wasm_app.h"
#include "wa-inc/timer_wasm_app.h"
#include "wa-inc/request.h"
int num = 0;
void publish_overheat_event()
{
attr_container_t *event;
event = attr_container_create("event");
attr_container_set_string(&event, "warning", "temperature is over high");
printf("###app publish event begin ###\n");
api_publish_event("alert/overheat", FMT_ATTR_CONTAINER, event,
attr_container_get_serialize_length(event));
printf("###app publish event end ###\n");
attr_container_destroy(event);
}
/* Timer callback */
void timer1_update(user_timer_t timer)
{
printf("Timer update %d\n", num++);
publish_overheat_event();
}
void start_timer()
{
user_timer_t timer;
/* set up a timer */
timer = api_timer_create(1000, true, false, timer1_update);
api_timer_restart(timer, 1000);
}
void on_init()
{
start_timer();
}
void on_destroy()
{
/* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wasm_app.h"
#include "wa-inc/request.h"
uint32 mid;
unsigned long sender;
void over_heat_event_handler(request_t *request)
{
response_t response[1];
attr_container_t *payload;
payload = attr_container_create("wasm app response payload");
if (payload == NULL)
return;
attr_container_set_string(&payload, "key1", "value1");
attr_container_set_string(&payload, "key2", "value2");
response->mid = mid;
response->reciever = sender;
set_response(response, CONTENT_2_05,
FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload));
printf("reciver: %lu, mid:%d\n", response->reciever, response->mid);
api_response_send(response);
attr_container_destroy(payload);
}
void res1_handler(request_t *request)
{
mid = request->mid;
sender = request->sender;
api_subscribe_event("alert/overheat", over_heat_event_handler);
}
void on_init()
{
/* register resource uri */
api_register_resource_handler("/res1", res1_handler);
}
void on_destroy()
{
/* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wasm_app.h"
#include "wa-inc/request.h"
#include "wa-inc/timer_wasm_app.h"
/* User global variable */
int num = 0;
/* Timer callback */
void timer1_update(user_timer_t timer)
{
if (num < 2)
num++;
}
void res1_handler(request_t *request)
{
user_timer_t timer;
/* set up a timer */
timer = api_timer_create(1000, true, false, timer1_update);
api_timer_restart(timer, 1000);
response_t response[1];
make_response_for_request(request, response);
set_response(response, CONTENT_2_05,
FMT_ATTR_CONTAINER, NULL, 0);
api_response_send(response);
}
void res2_handler(request_t *request)
{
response_t response[1];
attr_container_t *payload;
if (num == 2) {
attr_container_t *payload;
printf("### user resource 1 handler called\n");
payload = attr_container_create("wasm app response payload");
if (payload == NULL)
return;
attr_container_set_int(&payload, "num", num);
make_response_for_request(request, response);
set_response(response, CONTENT_2_05,
FMT_ATTR_CONTAINER, (const char *)payload,
attr_container_get_serialize_length(payload));
printf("reciver: %lu, mid:%d\n", response->reciever, response->mid);
api_response_send(response);
attr_container_destroy(payload);
}
}
void on_init()
{
/* register resource uri */
api_register_resource_handler("/res1", res1_handler);
api_register_resource_handler("/check_timer", res2_handler);
}
void on_destroy()
{
/* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wasm_app.h"
#include "wa-inc/request.h"
#include "wa-inc/sensor.h"
uint32 mid;
unsigned long sender;
/* Sensor event callback*/
void sensor_event_handler(sensor_t sensor, attr_container_t *event,
void *user_data)
{
printf("### app get sensor event\n");
response_t response[1];
attr_container_t *payload;
payload = attr_container_create("wasm app response payload");
if (payload == NULL)
return;
attr_container_set_string(&payload, "key1", "value1");
attr_container_set_string(&payload, "key2", "value2");
response->mid = mid;
response->reciever = sender;
set_response(response, CONTENT_2_05,
FMT_ATTR_CONTAINER, (const char *)payload, attr_container_get_serialize_length(payload));
printf("reciver: %lu, mid:%d\n", response->reciever, response->mid);
api_response_send(response);
attr_container_destroy(payload);
}
void res1_handler(request_t *request)
{
mid = request->mid;
sender = request->sender;
sensor_t sensor;
char *user_data;
attr_container_t *config;
printf("### app on_init 1\n");
/* open a sensor */
user_data = malloc(100);
printf("### app on_init 2\n");
sensor = sensor_open("sensor_test", 0, sensor_event_handler, user_data);
printf("### app on_init 3\n");
/* config the sensor */
sensor_config(sensor, 2000, 0, 0);
printf("### app on_init 4\n");
}
void on_init()
{
/* register resource uri */
api_register_resource_handler("/res1", res1_handler);
}
void on_destroy()
{
/* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "wasm_app.h"
#include "wa-inc/request.h"
#include "wa-inc/sensor.h"
uint32 mid;
unsigned long sender;
sensor_t sensor;
/* Sensor event callback*/
void sensor_event_handler(sensor_t sensor, attr_container_t *event, void *user_data) {
printf("### app get sensor event\n");
response_t response[1];
attr_container_t *payload;
payload = attr_container_create("wasm app response payload");
if (payload == NULL)
return;
attr_container_set_string(&payload, "key1", "value1");
response->mid = mid;
response->reciever = sender;
set_response(response,
CONTENT_2_05,
FMT_ATTR_CONTAINER,
(const char *)payload,
attr_container_get_serialize_length(payload));
printf("reciver: %lu, mid:%d\n", response->reciever, response->mid);
api_response_send(response);
attr_container_destroy(payload);
}
void res1_handler(request_t *request)
{
mid = request->mid;
sender = request->sender;
char *user_data;
attr_container_t *config;
printf("### app on_init 1\n");
/* open a sensor */
user_data = malloc(100);
printf("### app on_init 2\n");
sensor = sensor_open("sensor_test", 0, sensor_event_handler, user_data);
printf("### app on_init 3\n");
}
void on_init()
{
/* register resource uri */
api_register_resource_handler("/res1", res1_handler);
}
void on_destroy()
{
if(NULL != sensor){
sensor_close(sensor);
}
}

View File

@ -0,0 +1,39 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
. ../../../set_dev_env.sh
CC=/opt/wasi-sdk/bin/clang
APP_DIR=$PWD
WAMR_DIR=${APP_DIR}/../../../../../
SDK_DIR=${WAMR_DIR}/wamr-sdk/out/simple-host-interp
APP_FRAMEWORK_DIR=${SDK_DIR}/app-sdk/wamr-app-framework
DEPS_DIR=${WAMR_DIR}/core/deps
for i in `ls *.c`
do
APP_SRC="$i"
OUT_FILE=${i%.*}.wasm
/opt/wasi-sdk/bin/clang -O3 \
-Wno-int-conversion \
-I${APP_FRAMEWORK_DIR}/include \
-I${DEPS_DIR} \
--target=wasm32 -O3 -z stack-size=4096 -Wl,--initial-memory=65536 \
--sysroot=${SDK_DIR}/app-sdk/libc-builtin-sysroot \
-L${APP_FRAMEWORK_DIR}/lib -lapp_framework \
-Wl,--allow-undefined-file=${SDK_DIR}/app-sdk/libc-builtin-sysroot/share/defined-symbols.txt \
-Wl,--no-threads,--strip-all,--no-entry -nostdlib \
-Wl,--export=on_init -Wl,--export=on_destroy \
-Wl,--export=on_request -Wl,--export=on_response \
-Wl,--export=on_sensor_event -Wl,--export=on_timer_callback \
-Wl,--export=on_connection_data \
-o ${OUT_FILE} \
${APP_SRC}
if [ -f ${OUT_FILE} ]; then
echo "build ${OUT_FILE} success"
else
echo "build ${OUT_FILE} fail"
fi
done

View File

@ -0,0 +1,10 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#!/bin/bash
cd $(dirname "$0")
./simple -s > /dev/null 2>&1 &

View File

@ -0,0 +1,9 @@
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#!/bin/bash
ps aux | grep -ie host_tool | awk '{print $2}' | xargs kill -9 &
ps aux | grep -ie simple | awk '{print $2}' | xargs kill -9 &

View File

@ -0,0 +1,19 @@
The description of each case in the test suites, should add descriptions in this file when new cases created in the future.
suite 01-life-cycle:
case 01-install:
install or uninstall apps for times and query apps to see if the app list is expected.
case 02-request:
send request to an app, the app will respond specific attribute objects, host side should get them.
case 03-event:
register event to an app, the app will send event back periodically, host side should get some payload.
case 04-request_internal:
install 2 apps, host sends request to app2, then app2 sends request to app1, finally app1 respond specific payload to host, host side will check it.
case 05-event_internal:
install 2 apps, host sends request to app2, then app2 subscribe app1's event, finally app1 respond specific payload to host, host side will check it.
case 06-timer:
host send request to an app, the app then start a timer, when time goes by 2 seconds, app will respond specific payload to host, host side will check it.
case 07-sensor:
open sensor in app and then config the sensor in on_init, finally app will respond specific payload to host, host side will check it.
case 08-on_destroy:
open sensor in app in on_init, and close the sensor in on_destroy, host should install and uninstall the app successfully.

View File

@ -34,6 +34,9 @@ elseif (WAMR_BUILD_TARGET STREQUAL "AMD_64")
add_definitions(-DBUILD_TARGET_AMD_64)
elseif (WAMR_BUILD_TARGET STREQUAL "X86_32")
add_definitions(-DBUILD_TARGET_X86_32)
elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*")
add_definitions(-DBUILD_TARGET_AARCH64)
add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}")
elseif (WAMR_BUILD_TARGET MATCHES "ARM.*")
add_definitions(-DBUILD_TARGET_ARM)
add_definitions(-DBUILD_TARGET="${WAMR_BUILD_TARGET}")
@ -44,7 +47,7 @@ endif ()
message ("-- Build as target ${WAMR_BUILD_TARGET}")
if (CMAKE_SIZEOF_VOID_P EQUAL 8)
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*")
# Add -fPIC flag if build as 64-bit
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")

View File

@ -14,7 +14,7 @@ print_help()
{
printf("Usage: wamrc [options] -o output_file wasm_file\n");
printf(" --target=<arch-name> Set the target arch, which has the general format: <arch><sub>\n");
printf(" <arch> = x86_64, i386, arm, thumb, mips.\n");
printf(" <arch> = x86_64, i386, aarch64, arm, thumb, mips.\n");
printf(" Default is host arch, e.g. x86_64\n");
printf(" <sub> = for ex. on arm or thumb: v5, v6m, v7a, v7m, etc.\n");
printf(" Use --target=help to list supported targets\n");