Implement XIP feature and enable ARC target support (#694)

Implement XIP (Execution In Place) feature for AOT mode to enable running the AOT code inside AOT file directly, without memory mapping the executable memory for AOT code and applying relocations for text section. Developer can use wamrc with "--enable-indirect-mode --disable-llvm-intrinsics" flags to generate the AOT file and run iwasm with "--xip" flag. Known issues: there might still be some relocations in the text section which access the ".rodata" like sections.

And also enable ARC target support for both interpreter mode and AOT mode.

Signed-off-by: Wenyong Huang <wenyong.huang@intel.com>
This commit is contained in:
Wenyong Huang 2021-08-12 17:44:39 +08:00 committed by GitHub
parent 8fd89bd415
commit db695fada4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 2613 additions and 263 deletions

View File

@ -42,6 +42,8 @@ elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32" OR WAMR_BUILD_TARGET STREQUAL "RISC
add_definitions(-DBUILD_TARGET_RISCV32_ILP32D)
elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32")
add_definitions(-DBUILD_TARGET_RISCV32_ILP32)
elseif (WAMR_BUILD_TARGET STREQUAL "ARC")
add_definitions(-DBUILD_TARGET_ARC)
else ()
message (FATAL_ERROR "-- WAMR build target isn't set")
endif ()

View File

@ -32,29 +32,44 @@
#define REQUES_PACKET_VER 1
#define REQUEST_PACKET_FIX_PART_LEN 18
#define REQUEST_PACKET_URL_OFFSET REQUEST_PACKET_FIX_PART_LEN
#define REQUEST_PACKET_URL_LEN *((uint16*)( (char*) buffer + 12))) //!!! to ensure little endian
#define REQUEST_PACKET_PAYLOAD_LEN *((uint32*)( (char*) buffer + 14))) //!!! to ensure little endian
#define REQUEST_PACKET_URL_LEN *((uint16*)((char*) buffer + 12)) /* to ensure little endian */
#define REQUEST_PACKET_PAYLOAD_LEN *((uint32*)((char*) buffer + 14)) /* to ensure little endian */
#define REQUEST_PACKET_URL(buffer) ((char*) buffer + REQUEST_PACKET_URL_OFFSET)
#define REQUEST_PACKET_PAYLOAD(buffer) ((char*) buffer + REQUEST_PACKET_URL_OFFSET + REQUEST_PACKET_URL_LEN(buffer))
#define RESPONSE_PACKET_FIX_PART_LEN 16
char * pack_request(request_t *request, int * size)
char *
pack_request(request_t *request, int *size)
{
int url_len = strlen(request->url) + 1;
int len = REQUEST_PACKET_FIX_PART_LEN + url_len + request->payload_len;
char * packet = (char*) WA_MALLOC(len);
if (packet == NULL)
uint16 u16;
uint32 u32;
char *packet;
if ((packet = (char*) WA_MALLOC(len)) == NULL)
return NULL;
// TODO: ensure little endian for words and dwords
/* TODO: ensure little endian for words and dwords */
*packet = REQUES_PACKET_VER;
*((uint8*) (packet + 1)) = request->action;
*((uint16*) (packet + 2)) = htons(request->fmt);
*((uint32*) (packet + 4)) = htonl(request->mid);
*((uint32*) (packet + 8)) = htonl(request->sender);
*((uint16*) (packet + 12)) = htons(url_len);
*((uint32*) (packet + 14)) = htonl(request->payload_len);
u16 = htons(request->fmt);
memcpy(packet + 2, &u16, 2);
u32 = htonl(request->mid);
memcpy(packet + 4, &u32, 4);
u32 = htonl(request->sender);
memcpy(packet + 8, &u32, 4);
u16 = htons(url_len);
memcpy(packet + 12, &u16, 2);
u32 = htonl(request->payload_len);
memcpy(packet + 14, &u32, 4);
strcpy(packet + REQUEST_PACKET_URL_OFFSET, request->url);
memcpy(packet + REQUEST_PACKET_URL_OFFSET + url_len, request->payload,
request->payload_len);
@ -63,35 +78,53 @@ char * pack_request(request_t *request, int * size)
return packet;
}
void free_req_resp_packet(char * packet)
void
free_req_resp_packet(char *packet)
{
WA_FREE(packet);
}
request_t * unpack_request(char * packet, int size, request_t * request)
request_t *
unpack_request(char *packet, int size, request_t *request)
{
uint16 url_len, u16;
uint32 payload_len, u32;
if (*packet != REQUES_PACKET_VER) {
return NULL;
}
if (size < REQUEST_PACKET_FIX_PART_LEN) {
return NULL;
}
uint16 url_len = ntohs(*((uint16*) (packet + 12)));
uint32 payload_len = ntohl(*((uint32*) (packet + 14)));
if (size != ( REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len)) {
memcpy(&u16, packet + 12, 2);
url_len = ntohs(u16);
memcpy(&u32, packet + 14, 4);
payload_len = ntohl(u32);
if (size != (REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len)) {
return NULL;
}
if (*(packet + REQUEST_PACKET_FIX_PART_LEN + url_len - 1) != 0) {
return NULL;
}
request->action = *((uint8*) (packet + 1));
request->fmt = ntohs(*((uint16*) (packet + 2)));
request->mid = ntohl(*((uint32*) (packet + 4)));
request->sender = ntohl(*((uint32*) (packet + 8)));
memcpy(&u16, packet + 2, 2);
request->fmt = ntohs(u16);
memcpy(&u32, packet + 4, 4);
request->mid = ntohl(u32);
memcpy(&u32, packet + 8, 4);
request->sender = ntohl(u32);
request->payload_len = payload_len;
request->url = REQUEST_PACKET_URL(packet);
if (payload_len > 0)
request->payload = packet + REQUEST_PACKET_URL_OFFSET + url_len;
else
@ -100,20 +133,33 @@ request_t * unpack_request(char * packet, int size, request_t * request)
return request;
}
char * pack_response(response_t *response, int * size)
char *
pack_response(response_t *response, int *size)
{
int len = RESPONSE_PACKET_FIX_PART_LEN + response->payload_len;
char * packet = (char*) WA_MALLOC(len);
if (packet == NULL)
uint16 u16;
uint32 u32;
char *packet;
if ((packet = (char*) WA_MALLOC(len)) == NULL)
return NULL;
// TODO: ensure little endian for words and dwords
/* TODO: ensure little endian for words and dwords */
*packet = REQUES_PACKET_VER;
*((uint8*) (packet + 1)) = response->status;
*((uint16*) (packet + 2)) = htons(response->fmt);
*((uint32*) (packet + 4)) = htonl(response->mid);
*((uint32*) (packet + 8)) = htonl(response->reciever);
*((uint32*) (packet + 12)) = htonl(response->payload_len);
u16 = htons(response->fmt);
memcpy(packet + 2, &u16, 2);
u32 = htonl(response->mid);
memcpy(packet + 4, &u32, 4);
u32 = htonl(response->reciever);
memcpy(packet + 8, &u32, 4);
u32 = htonl(response->payload_len);
memcpy(packet + 12, &u32, 4);
memcpy(packet + RESPONSE_PACKET_FIX_PART_LEN, response->payload,
response->payload_len);
@ -121,20 +167,34 @@ char * pack_response(response_t *response, int * size)
return packet;
}
response_t * unpack_response(char * packet, int size, response_t * response)
response_t *
unpack_response(char *packet, int size, response_t *response)
{
uint16 u16;
uint32 payload_len, u32;
if (*packet != REQUES_PACKET_VER)
return NULL;
if (size < RESPONSE_PACKET_FIX_PART_LEN)
return NULL;
uint32 payload_len = ntohl(*((uint32*) (packet + 12)));
if (size != ( RESPONSE_PACKET_FIX_PART_LEN + payload_len))
memcpy(&u32, packet + 12, 4);
payload_len = ntohl(u32);
if (size != (RESPONSE_PACKET_FIX_PART_LEN + payload_len))
return NULL;
response->status = *((uint8*) (packet + 1));
response->fmt = ntohs(*((uint16*) (packet + 2)));
response->mid = ntohl(*((uint32*) (packet + 4)));
response->reciever = ntohl(*((uint32*) (packet + 8)));
memcpy(&u16, packet + 2, 2);
response->fmt = ntohs(u16);
memcpy(&u32, packet + 4, 4);
response->mid = ntohl(u32);
memcpy(&u32, packet + 8, 4);
response->reciever = ntohl(u32);
response->payload_len = payload_len;
if (payload_len > 0)
response->payload = packet + RESPONSE_PACKET_FIX_PART_LEN;
@ -144,7 +204,8 @@ response_t * unpack_response(char * packet, int size, response_t * response)
return response;
}
request_t *clone_request(request_t *request)
request_t *
clone_request(request_t *request)
{
/* deep clone */
request_t *req = (request_t *) WA_MALLOC(sizeof(request_t));
@ -164,12 +225,14 @@ request_t *clone_request(request_t *request)
req->payload_len = request->payload_len;
if (request->payload_len) {
req->payload = (char *) WA_MALLOC(request->payload_len);
req->payload = (char *)WA_MALLOC(request->payload_len);
if (!req->payload)
goto fail;
memcpy(req->payload, request->payload, request->payload_len);
} else {
// when payload_len is 0, the payload may be used for carrying some handle or integer
}
else {
/* when payload_len is 0, the payload may be used for
carrying some handle or integer */
req->payload = request->payload;
}
@ -180,7 +243,8 @@ fail:
return NULL;
}
void request_cleaner(request_t *request)
void
request_cleaner(request_t *request)
{
if (request->url != NULL)
WA_FREE(request->url);
@ -190,7 +254,8 @@ void request_cleaner(request_t *request)
WA_FREE(request);
}
void response_cleaner(response_t * response)
void
response_cleaner(response_t *response)
{
if (response->payload != NULL && response->payload_len > 0)
WA_FREE(response->payload);
@ -198,9 +263,11 @@ void response_cleaner(response_t * response)
WA_FREE(response);
}
response_t * clone_response(response_t * response)
response_t *
clone_response(response_t *response)
{
response_t *clone = (response_t *) WA_MALLOC(sizeof(response_t));
response_t *clone = (response_t *)WA_MALLOC(sizeof(response_t));
if (clone == NULL)
return NULL;
@ -215,8 +282,10 @@ response_t * clone_response(response_t * response)
if (!clone->payload)
goto fail;
memcpy(clone->payload, response->payload, response->payload_len);
} else {
// when payload_len is 0, the payload may be used for carrying some handle or integer
}
else {
/* when payload_len is 0, the payload may be used for
carrying some handle or integer */
clone->payload = response->payload;
}
return clone;
@ -226,8 +295,9 @@ fail:
return NULL;
}
response_t * set_response(response_t * response, int status, int fmt,
const char *payload, int payload_len)
response_t *
set_response(response_t *response, int status, int fmt,
const char *payload, int payload_len)
{
response->payload = (void *)payload;
response->payload_len = payload_len;
@ -236,8 +306,9 @@ response_t * set_response(response_t * response, int status, int fmt,
return response;
}
response_t * make_response_for_request(request_t * request,
response_t * response)
response_t *
make_response_for_request(request_t *request,
response_t *response)
{
response->mid = request->mid;
response->reciever = request->sender;
@ -245,10 +316,12 @@ response_t * make_response_for_request(request_t * request,
return response;
}
request_t * init_request(request_t * request, char *url, int action, int fmt,
void *payload, int payload_len)
static unsigned int mid = 0;
request_t *
init_request(request_t *request, char *url, int action, int fmt,
void *payload, int payload_len)
{
static unsigned int mid = 0;
request->url = url;
request->action = action;
request->fmt = fmt;
@ -269,7 +342,8 @@ request_t * init_request(request_t * request, char *url, int action, int fmt,
3. it ensure the leading_str "/abc" can pass "/abc?cde
*/
int check_url_start(const char* url, int url_len, const char * leading_str)
int
check_url_start(const char *url, int url_len, const char *leading_str)
{
int offset = 0;
if (*leading_str == '/')
@ -284,28 +358,27 @@ int check_url_start(const char* url, int url_len, const char * leading_str)
if (len == 0)
return 0;
// ensure leading_str not end with "/"
/* ensure leading_str not end with "/" */
if (leading_str[len - 1] == '/') {
len--;
if (len == 0)
return 0;
}
// equal length
/* equal length */
if (url_len == len) {
if (memcmp(url, leading_str, url_len) == 0) {
return (offset + len);
} else {
}
else {
return 0;
}
}
if (url_len < len)
return 0;
else if (memcmp(url, leading_str, len) != 0)
return 0;
else if (url[len] != '/' && url[len] != '?')
return 0;
else
@ -318,7 +391,8 @@ int check_url_start(const char* url, int url_len, const char * leading_str)
// * sample 3: /abcd*, match any url started with "/abcd"
// * sample 4: /abcd/*, exclude "/abcd"
bool match_url(char * pattern, char * matched)
bool
match_url(char *pattern, char *matched)
{
if (*pattern == '/')
pattern++;
@ -352,17 +426,19 @@ bool match_url(char * pattern, char * matched)
return false;
} else if (pattern[len - 1] == '*') {
}
else if (pattern[len - 1] == '*') {
if (pattern[len - 2] == '/') {
if (strncmp(pattern, matched, len - 1) == 0)
return true;
else
return false;
} else {
}
else {
return (strncmp(pattern, matched, len - 1) == 0);
}
} else {
}
else {
return (strcmp(pattern, matched) == 0);
}
}
@ -371,10 +447,11 @@ bool match_url(char * pattern, char * matched)
* get the value of the key from following format buffer:
* key1=value1;key2=value2;key3=value3
*/
char * find_key_value(char * buffer, int buffer_len, char * key, char * value,
int value_len, char delimiter)
char *
find_key_value(char *buffer, int buffer_len, char *key, char *value,
int value_len, char delimiter)
{
char * p = buffer;
char *p = buffer;
int remaining = buffer_len;
int key_len = strlen(key);
@ -387,13 +464,13 @@ char * find_key_value(char * buffer, int buffer_len, char * key, char * value,
if (remaining <= key_len)
return NULL;
// find the key
/* find the key */
if (0 == strncmp(p, key, key_len) && p[key_len] == '=') {
p += (key_len + 1);
remaining -= (key_len + 1);
char * v = value;
memset(value, 0, value_len);
value_len--; // ensure last char is 0
value_len--; /* ensure last char is 0 */
while (*p != delimiter && remaining > 0 && value_len > 0) {
*v++ = *p++;
remaining--;
@ -402,7 +479,7 @@ char * find_key_value(char * buffer, int buffer_len, char * key, char * value,
return value;
}
// goto next key
/* goto next key */
while (*p != delimiter && remaining > 0) {
p++;
remaining--;

View File

@ -653,7 +653,8 @@ wasm_app_module_install(request_t * msg)
AOT_SECTION_TYPE_FUNCTION,
AOT_SECTION_TYPE_EXPORT,
AOT_SECTION_TYPE_RELOCATION,
AOT_SECTION_TYPE_SIGANATURE
AOT_SECTION_TYPE_SIGANATURE,
AOT_SECTION_TYPE_CUSTOM,
};
aot_file = &wasm_app_file->u.aot;
@ -1375,7 +1376,8 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
/* Notes: integers are always little endian encoded in AOT file */
if (!is_little_endian())
exchange_uint32(p);
if (cur_section->section_type < AOT_SECTION_TYPE_SIGANATURE) {
if (cur_section->section_type < AOT_SECTION_TYPE_SIGANATURE
|| cur_section->section_type == AOT_SECTION_TYPE_CUSTOM) {
recv_ctx.phase = Phase_AOT_Section_Size;
recv_ctx.size_in_phase = 0;
}

View File

@ -29,12 +29,13 @@ extern "C" {
typedef enum AOTSectionType {
AOT_SECTION_TYPE_TARGET_INFO = 0,
AOT_SECTION_TYPE_INIT_DATA,
AOT_SECTION_TYPE_TEXT,
AOT_SECTION_TYPE_FUNCTION,
AOT_SECTION_TYPE_EXPORT,
AOT_SECTION_TYPE_RELOCATION,
AOT_SECTION_TYPE_SIGANATURE
AOT_SECTION_TYPE_INIT_DATA = 1,
AOT_SECTION_TYPE_TEXT = 2,
AOT_SECTION_TYPE_FUNCTION = 3,
AOT_SECTION_TYPE_EXPORT = 4,
AOT_SECTION_TYPE_RELOCATION = 5,
AOT_SECTION_TYPE_SIGANATURE = 6,
AOT_SECTION_TYPE_CUSTOM = 100,
} AOTSectionType;
enum {

View File

@ -19,7 +19,8 @@
&& !defined(BUILD_TARGET_RISCV64_LP64D) \
&& !defined(BUILD_TARGET_RISCV64_LP64) \
&& !defined(BUILD_TARGET_RISCV32_ILP32D) \
&& !defined(BUILD_TARGET_RISCV32_ILP32)
&& !defined(BUILD_TARGET_RISCV32_ILP32) \
&& !defined(BUILD_TARGET_ARC)
#if defined(__x86_64__) || defined(__x86_64)
#define BUILD_TARGET_X86_64
#elif defined(__amd64__) || defined(__amd64)
@ -42,6 +43,8 @@
#define BUILD_TARGET_RISCV64_LP64D
#elif defined(__riscv) && (__riscv_xlen == 32)
#define BUILD_TARGET_RISCV32_ILP32D
#elif defined(__arc__)
#define BUILD_TARGET_ARC
#else
#error "Build target isn't set"
#endif
@ -237,7 +240,9 @@
#define APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT 1 / 3
/* Default min/max heap size of each app */
#ifndef APP_HEAP_SIZE_DEFAULT
#define APP_HEAP_SIZE_DEFAULT (8 * 1024)
#endif
#define APP_HEAP_SIZE_MIN (256)
#define APP_HEAP_SIZE_MAX (512 * 1024 * 1024)

View File

@ -0,0 +1,407 @@
/*
* Copyright (C) 2021 XiaoMi Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "aot_intrinsic.h"
typedef struct {
const char *llvm_intrinsic;
const char *native_intrinsic;
uint64 flag;
} aot_intrinsic;
static const aot_intrinsic g_intrinsic_mapping[] = {
{ "llvm.experimental.constrained.fadd.f32", "aot_intrinsic_fadd_f32",
AOT_INTRINSIC_FLAG_F32_FADD },
{ "llvm.experimental.constrained.fadd.f64", "aot_intrinsic_fadd_f64",
AOT_INTRINSIC_FLAG_F64_FADD },
{ "llvm.experimental.constrained.fsub.f32", "aot_intrinsic_fsub_f32",
AOT_INTRINSIC_FLAG_F32_FSUB },
{ "llvm.experimental.constrained.fsub.f64", "aot_intrinsic_fsub_f64",
AOT_INTRINSIC_FLAG_F64_FSUB },
{ "llvm.experimental.constrained.fmul.f32", "aot_intrinsic_fmul_f32",
AOT_INTRINSIC_FLAG_F32_FMUL },
{ "llvm.experimental.constrained.fmul.f64", "aot_intrinsic_fmul_f64",
AOT_INTRINSIC_FLAG_F64_FMUL },
{ "llvm.experimental.constrained.fdiv.f32", "aot_intrinsic_fdiv_f32",
AOT_INTRINSIC_FLAG_F32_FDIV },
{ "llvm.experimental.constrained.fdiv.f64", "aot_intrinsic_fdiv_f64",
AOT_INTRINSIC_FLAG_F64_FDIV },
{ "llvm.fabs.f32", "aot_intrinsic_fabs_f32", AOT_INTRINSIC_FLAG_F32_FABS },
{ "llvm.fabs.f64", "aot_intrinsic_fabs_f64", AOT_INTRINSIC_FLAG_F64_FABS },
{ "llvm.ceil.f32", "aot_intrinsic_ceil_f32", AOT_INTRINSIC_FLAG_F32_CEIL },
{ "llvm.ceil.f64", "aot_intrinsic_ceil_f64", AOT_INTRINSIC_FLAG_F64_CEIL },
{ "llvm.floor.f32", "aot_intrinsic_floor_f32",
AOT_INTRINSIC_FLAG_F32_FLOOR },
{ "llvm.floor.f64", "aot_intrinsic_floor_f64",
AOT_INTRINSIC_FLAG_F64_FLOOR },
{ "llvm.trunc.f32", "aot_intrinsic_trunc_f32",
AOT_INTRINSIC_FLAG_F32_TRUNC },
{ "llvm.trunc.f64", "aot_intrinsic_trunc_f64",
AOT_INTRINSIC_FLAG_F64_TRUNC },
{ "llvm.rint.f32", "aot_intrinsic_rint_f32", AOT_INTRINSIC_FLAG_F32_RINT },
{ "llvm.rint.f64", "aot_intrinsic_rint_f64", AOT_INTRINSIC_FLAG_F64_RINT },
{ "llvm.sqrt.f32", "aot_intrinsic_sqrt_f32", AOT_INTRINSIC_FLAG_F32_SQRT },
{ "llvm.sqrt.f64", "aot_intrinsic_sqrt_f64", AOT_INTRINSIC_FLAG_F64_SQRT },
{ "llvm.copysign.f32", "aot_intrinsic_copysign_f32",
AOT_INTRINSIC_FLAG_F32_COPYSIGN },
{ "llvm.copysign.f64", "aot_intrinsic_copysign_f64",
AOT_INTRINSIC_FLAG_F64_COPYSIGN },
{ "llvm.minnum.f32", "aot_intrinsic_fmin_f32", AOT_INTRINSIC_FLAG_F32_MIN },
{ "llvm.minnum.f64", "aot_intrinsic_fmin_f64", AOT_INTRINSIC_FLAG_F64_MIN },
{ "llvm.maxnum.f32", "aot_intrinsic_fmax_f32", AOT_INTRINSIC_FLAG_F32_MAX },
{ "llvm.maxnum.f64", "aot_intrinsic_fmax_f64", AOT_INTRINSIC_FLAG_F64_MAX },
{ "llvm.ctlz.i32", "aot_intrinsic_clz_i32", AOT_INTRINSIC_FLAG_I32_CLZ },
{ "llvm.ctlz.i64", "aot_intrinsic_clz_i64", AOT_INTRINSIC_FLAG_I64_CLZ },
{ "llvm.cttz.i32", "aot_intrinsic_ctz_i32", AOT_INTRINSIC_FLAG_I32_CTZ },
{ "llvm.cttz.i64", "aot_intrinsic_ctz_i64", AOT_INTRINSIC_FLAG_I64_CTZ },
{ "llvm.ctpop.i32", "aot_intrinsic_popcnt_i32", AOT_INTRINSIC_FLAG_I32_POPCNT },
{ "llvm.ctpop.i64", "aot_intrinsic_popcnt_i64", AOT_INTRINSIC_FLAG_I64_POPCNT },
};
static const uint32 g_intrinsic_count =
sizeof(g_intrinsic_mapping) / sizeof(aot_intrinsic);
float32
aot_intrinsic_fadd_f32(float32 a, float32 b)
{
return a + b;
}
float64
aot_intrinsic_fadd_f64(float64 a, float64 b)
{
return a + b;
}
float32
aot_intrinsic_fsub_f32(float32 a, float32 b)
{
return a - b;
}
float64
aot_intrinsic_fsub_f64(float64 a, float64 b)
{
return a - b;
}
float32
aot_intrinsic_fmul_f32(float32 a, float32 b)
{
return a * b;
}
float64
aot_intrinsic_fmul_f64(float64 a, float64 b)
{
return a * b;
}
float32
aot_intrinsic_fdiv_f32(float32 a, float32 b)
{
return a / b;
}
float64
aot_intrinsic_fdiv_f64(float64 a, float64 b)
{
return a / b;
}
float32
aot_intrinsic_fabs_f32(float32 a)
{
return (float32)fabs(a);
}
float64
aot_intrinsic_fabs_f64(float64 a)
{
return fabs(a);
}
float32
aot_intrinsic_ceil_f32(float32 a)
{
return (float32)ceilf(a);
}
float64
aot_intrinsic_ceil_f64(float64 a)
{
return ceil(a);
}
float32
aot_intrinsic_floor_f32(float32 a)
{
return (float32)floorf(a);
}
float64
aot_intrinsic_floor_f64(float64 a)
{
return floor(a);
}
float32
aot_intrinsic_trunc_f32(float32 a)
{
return (float32)trunc(a);
}
float64
aot_intrinsic_trunc_f64(float64 a)
{
return trunc(a);
}
float32
aot_intrinsic_rint_f32(float32 a)
{
return (float32)rint(a);
}
float64
aot_intrinsic_rint_f64(float64 a)
{
return rint(a);
}
float32
aot_intrinsic_sqrt_f32(float32 a)
{
return (float32)sqrt(a);
}
float64
aot_intrinsic_sqrt_f64(float64 a)
{
return sqrt(a);
}
float32
aot_intrinsic_copysign_f32(float32 a, float32 b)
{
return signbit(b) ? (float32)-fabs(a) : (float32)fabs(a);
}
float64
aot_intrinsic_copysign_f64(float64 a, float64 b)
{
return signbit(b) ? -fabs(a) : fabs(a);
}
float32
aot_intrinsic_fmin_f32(float32 a, float32 b)
{
if (isnan(a))
return a;
else if (isnan(b))
return b;
else
return (float32)fmin(a, b);
}
float64
aot_intrinsic_fmin_f64(float64 a, float64 b)
{
float64 c = fmin(a, b);
if (c==0 && a==b)
return signbit(a) ? a : b;
return c;
}
float32
aot_intrinsic_fmax_f32(float32 a, float32 b)
{
if (isnan(a))
return a;
else if (isnan(b))
return b;
else
return (float32)fmax(a, b);
}
float64
aot_intrinsic_fmax_f64(float64 a, float64 b)
{
float64 c = fmax(a, b);
if (c==0 && a==b)
return signbit(a) ? b : a;
return c;
}
uint32
aot_intrinsic_clz_i32(uint32 type)
{
uint32 num = 0;
if (type == 0)
return 32;
while (!(type & 0x80000000)) {
num++;
type <<= 1;
}
return num;
}
uint32
aot_intrinsic_clz_i64(uint64 type)
{
uint32 num = 0;
if (type == 0)
return 64;
while (!(type & 0x8000000000000000LL)) {
num++;
type <<= 1;
}
return num;
}
uint32
aot_intrinsic_ctz_i32(uint32 type)
{
uint32 num = 0;
if (type == 0)
return 32;
while (!(type & 1)) {
num++;
type >>= 1;
}
return num;
}
uint32
aot_intrinsic_ctz_i64(uint64 type)
{
uint32 num = 0;
if (type == 0)
return 64;
while (!(type & 1)) {
num++;
type >>= 1;
}
return num;
}
uint32
aot_intrinsic_popcnt_i32(uint32 u)
{
uint32 ret = 0;
while (u) {
u = (u & (u - 1));
ret++;
}
return ret;
}
uint32
aot_intrinsic_popcnt_i64(uint64 u)
{
uint32 ret = 0;
while (u) {
u = (u & (u - 1));
ret++;
}
return ret;
}
const char *
aot_intrinsic_get_symbol(const char *llvm_intrinsic)
{
uint32 cnt;
for (cnt = 0; cnt < g_intrinsic_count; cnt++) {
if (!strcmp(llvm_intrinsic, g_intrinsic_mapping[cnt].llvm_intrinsic)) {
return g_intrinsic_mapping[cnt].native_intrinsic;
}
}
return NULL;
}
#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
static void
add_intrinsic_capability(AOTCompContext *comp_ctx, uint64 flag)
{
uint64 group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag);
if (group < sizeof(comp_ctx->flags) / sizeof(uint64)) {
comp_ctx->flags[group] |= flag;
}
else {
bh_log(BH_LOG_LEVEL_WARNING, __FILE__, __LINE__,
"intrinsic exceeds max limit.");
}
}
static void
add_f32_common_intrinsics_for_thumb2_fpu(AOTCompContext *comp_ctx)
{
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FABS);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FADD);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FSUB);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FMUL);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_FDIV);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F32_SQRT);
}
static void
add_f64_common_intrinsics_for_thumb2_fpu(AOTCompContext *comp_ctx)
{
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FABS);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FADD);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FSUB);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FMUL);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_FDIV);
add_intrinsic_capability(comp_ctx, AOT_INTRINSIC_FLAG_F64_SQRT);
}
bool
aot_intrinsic_check_capability(const AOTCompContext *comp_ctx,
const char *llvm_intrinsic)
{
uint32 cnt;
uint64 flag;
uint64 group;
for (cnt = 0; cnt < g_intrinsic_count; cnt++) {
if (!strcmp(llvm_intrinsic, g_intrinsic_mapping[cnt].llvm_intrinsic)) {
flag = g_intrinsic_mapping[cnt].flag;
group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag);
flag &= AOT_INTRINSIC_FLAG_MASK;
if (group < sizeof(comp_ctx->flags) / sizeof(uint64)) {
if (comp_ctx->flags[group] & flag) {
return true;
}
}
else {
bh_log(BH_LOG_LEVEL_WARNING, __FILE__, __LINE__,
"intrinsic exceeds max limit.");
}
}
}
return false;
}
void
aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx)
{
memset(comp_ctx->flags, 0, sizeof(comp_ctx->flags));
if (!comp_ctx->target_cpu)
return;
if (!strncmp(comp_ctx->target_arch, "thumb", 5)) {
if (!strcmp(comp_ctx->target_cpu, "cortex-m4")) {
add_f32_common_intrinsics_for_thumb2_fpu(comp_ctx);
}
else if (!strcmp(comp_ctx->target_cpu, "cortex-m7")) {
add_f32_common_intrinsics_for_thumb2_fpu(comp_ctx);
add_f64_common_intrinsics_for_thumb2_fpu(comp_ctx);
}
}
}
#endif /* WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 */

View File

@ -0,0 +1,180 @@
/*
* Copyright (C) 2021 XiaoMi Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _AOT_INTRINSIC_H
#define _AOT_INTRINSIC_H
#if WASM_ENABLE_WAMR_COMPILER != 0
#include "aot_llvm.h"
#endif
#include "aot_runtime.h"
#ifdef __cplusplus
extern "C" {
#endif
#define AOT_INTRINSIC_GROUPS 2
/* Use uint64 as flag container:
* - The upper 16 bits are the intrinsic group number
* - The lower 48 bits are the intrinsic capability mask
*/
#define AOT_INTRINSIC_FLAG(group, value) \
((((uint64)(group & 0xffffLL)) << 48) | (uint64)value)
#define AOT_INTRINSIC_FLAG_MASK (0x0000ffffffffffffLL)
#define AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag) \
((((uint64)flag) >> 48) & 0xffffLL)
#define AOT_INTRINSIC_FLAG_F32_FADD AOT_INTRINSIC_FLAG(0, 0x000000000001)
#define AOT_INTRINSIC_FLAG_F32_FSUB AOT_INTRINSIC_FLAG(0, 0x000000000002)
#define AOT_INTRINSIC_FLAG_F32_FMUL AOT_INTRINSIC_FLAG(0, 0x000000000004)
#define AOT_INTRINSIC_FLAG_F32_FDIV AOT_INTRINSIC_FLAG(0, 0x000000000008)
#define AOT_INTRINSIC_FLAG_F32_FABS AOT_INTRINSIC_FLAG(0, 0x000000000010)
#define AOT_INTRINSIC_FLAG_F32_CEIL AOT_INTRINSIC_FLAG(0, 0x000000000020)
#define AOT_INTRINSIC_FLAG_F32_FLOOR AOT_INTRINSIC_FLAG(0, 0x000000000040)
#define AOT_INTRINSIC_FLAG_F32_TRUNC AOT_INTRINSIC_FLAG(0, 0x000000000080)
#define AOT_INTRINSIC_FLAG_F32_RINT AOT_INTRINSIC_FLAG(0, 0x000000000100)
#define AOT_INTRINSIC_FLAG_F32_SQRT AOT_INTRINSIC_FLAG(0, 0x000000000200)
#define AOT_INTRINSIC_FLAG_F32_COPYSIGN AOT_INTRINSIC_FLAG(0, 0x000000000400)
#define AOT_INTRINSIC_FLAG_F32_MIN AOT_INTRINSIC_FLAG(0, 0x000000000800)
#define AOT_INTRINSIC_FLAG_F32_MAX AOT_INTRINSIC_FLAG(0, 0x000000001000)
#define AOT_INTRINSIC_FLAG_I32_CLZ AOT_INTRINSIC_FLAG(0, 0x000000002000)
#define AOT_INTRINSIC_FLAG_I32_CTZ AOT_INTRINSIC_FLAG(0, 0x000000004000)
#define AOT_INTRINSIC_FLAG_I32_POPCNT AOT_INTRINSIC_FLAG(0, 0x000000008000)
#define AOT_INTRINSIC_FLAG_F64_FADD AOT_INTRINSIC_FLAG(1, 0x000000000001)
#define AOT_INTRINSIC_FLAG_F64_FSUB AOT_INTRINSIC_FLAG(1, 0x000000000002)
#define AOT_INTRINSIC_FLAG_F64_FMUL AOT_INTRINSIC_FLAG(1, 0x000000000004)
#define AOT_INTRINSIC_FLAG_F64_FDIV AOT_INTRINSIC_FLAG(1, 0x000000000008)
#define AOT_INTRINSIC_FLAG_F64_FABS AOT_INTRINSIC_FLAG(1, 0x000000000010)
#define AOT_INTRINSIC_FLAG_F64_CEIL AOT_INTRINSIC_FLAG(1, 0x000000000020)
#define AOT_INTRINSIC_FLAG_F64_FLOOR AOT_INTRINSIC_FLAG(1, 0x000000000040)
#define AOT_INTRINSIC_FLAG_F64_TRUNC AOT_INTRINSIC_FLAG(1, 0x000000000080)
#define AOT_INTRINSIC_FLAG_F64_RINT AOT_INTRINSIC_FLAG(1, 0x000000000100)
#define AOT_INTRINSIC_FLAG_F64_SQRT AOT_INTRINSIC_FLAG(1, 0x000000000200)
#define AOT_INTRINSIC_FLAG_F64_COPYSIGN AOT_INTRINSIC_FLAG(1, 0x000000000400)
#define AOT_INTRINSIC_FLAG_F64_MIN AOT_INTRINSIC_FLAG(1, 0x000000000800)
#define AOT_INTRINSIC_FLAG_F64_MAX AOT_INTRINSIC_FLAG(1, 0x000000001000)
#define AOT_INTRINSIC_FLAG_I64_CLZ AOT_INTRINSIC_FLAG(1, 0x000000002000)
#define AOT_INTRINSIC_FLAG_I64_CTZ AOT_INTRINSIC_FLAG(1, 0x000000004000)
#define AOT_INTRINSIC_FLAG_I64_POPCNT AOT_INTRINSIC_FLAG(1, 0x000000008000)
float32
aot_intrinsic_fadd_f32(float32 a, float32 b);
float64
aot_intrinsic_fadd_f64(float64 a, float64 b);
float32
aot_intrinsic_fsub_f32(float32 a, float32 b);
float64
aot_intrinsic_fsub_f64(float64 a, float64 b);
float32
aot_intrinsic_fmul_f32(float32 a, float32 b);
float64
aot_intrinsic_fmul_f64(float64 a, float64 b);
float32
aot_intrinsic_fdiv_f32(float32 a, float32 b);
float64
aot_intrinsic_fdiv_f64(float64 a, float64 b);
float32
aot_intrinsic_fabs_f32(float32 a);
float64
aot_intrinsic_fabs_f64(float64 a);
float32
aot_intrinsic_ceil_f32(float32 a);
float64
aot_intrinsic_ceil_f64(float64 a);
float32
aot_intrinsic_floor_f32(float32 a);
float64
aot_intrinsic_floor_f64(float64 a);
float32
aot_intrinsic_trunc_f32(float32 a);
float64
aot_intrinsic_trunc_f64(float64 a);
float32
aot_intrinsic_rint_f32(float32 a);
float64
aot_intrinsic_rint_f64(float64 a);
float32
aot_intrinsic_sqrt_f32(float32 a);
float64
aot_intrinsic_sqrt_f64(float64 a);
float32
aot_intrinsic_copysign_f32(float32 a, float32 b);
float64
aot_intrinsic_copysign_f64(float64 a, float64 b);
float32
aot_intrinsic_fmin_f32(float32 a, float32 b);
float64
aot_intrinsic_fmin_f64(float64 a, float64 b);
float32
aot_intrinsic_fmax_f32(float32 a, float32 b);
float64
aot_intrinsic_fmax_f64(float64 a, float64 b);
uint32
aot_intrinsic_clz_i32(uint32 type);
uint32
aot_intrinsic_clz_i64(uint64 type);
uint32
aot_intrinsic_ctz_i32(uint32 type);
uint32
aot_intrinsic_ctz_i64(uint64 type);
uint32
aot_intrinsic_popcnt_i32(uint32 u);
uint32
aot_intrinsic_popcnt_i64(uint64 u);
const char *
aot_intrinsic_get_symbol(const char *llvm_intrinsic);
#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
bool
aot_intrinsic_check_capability(const AOTCompContext *comp_ctx,
const char *llvm_intrinsic);
void
aot_intrinsic_fill_capability_flags(AOTCompContext *comp_ctx);
#endif
#ifdef __cplusplus
}
#endif
#endif /* end of _AOT_INTRINSIC_H */

View File

@ -181,6 +181,8 @@ GET_U64_FROM_ADDR(uint32 *addr)
#define E_MACHINE_IA_64 50 /* Intel Merced */
#define E_MACHINE_MIPS_X 51 /* Stanford MIPS-X */
#define E_MACHINE_X86_64 62 /* AMD x86-64 architecture */
#define E_MACHINE_ARC_COMPACT 93 /* ARC International ARCompact */
#define E_MACHINE_ARC_COMPACT2 195 /* Synopsys ARCompact V2 */
#define E_MACHINE_XTENSA 94 /* Tensilica Xtensa Architecture */
#define E_MACHINE_RISCV 243 /* RISC-V 32/64 */
#define E_MACHINE_WIN_X86_64 0x8664 /* Windowx x86-64 architecture */
@ -261,6 +263,10 @@ get_aot_file_target(AOTTargetInfo *target_info,
case E_MACHINE_RISCV:
machine_type = "riscv";
break;
case E_MACHINE_ARC_COMPACT:
case E_MACHINE_ARC_COMPACT2:
machine_type = "arc";
break;
default:
set_error_buf_v(error_buf, error_buf_size,
"unknown machine type %d",
@ -368,6 +374,90 @@ fail:
return false;
}
static void *
get_native_symbol_by_name(const char *name)
{
void *func = NULL;
uint32 symnum = 0;
SymbolMap *sym = NULL;
sym = get_target_symbol_map(&symnum);
while (symnum--) {
if (strcmp(sym->symbol_name, name) == 0) {
func = sym->symbol_addr;
break;
}
sym++;
}
return func;
}
static bool
load_native_symbol_section(const uint8 *buf, const uint8 *buf_end,
AOTModule *module,
char *error_buf, uint32 error_buf_size)
{
const uint8 *p = buf, *p_end = buf_end;
uint32 cnt;
int32 i;
const char *symbol;
read_uint32(p, p_end, cnt);
module->native_symbol_count = cnt;
if (cnt > 0) {
module->native_symbol_list = wasm_runtime_malloc(cnt * sizeof(void *));
if (module->native_symbol_list == NULL) {
set_error_buf(error_buf, error_buf_size,
"malloc native symbol list failed");
goto fail;
}
for (i = cnt - 1; i >= 0; i--) {
read_string(p, p_end, symbol);
module->native_symbol_list[i] = get_native_symbol_by_name(symbol);
if (module->native_symbol_list[i] == NULL) {
set_error_buf_v(error_buf, error_buf_size,
"missing native symbol: %s", symbol);
goto fail;
}
}
}
return true;
fail:
return false;
}
static bool
load_custom_section(const uint8 *buf, const uint8 *buf_end,
AOTModule *module,
char *error_buf, uint32 error_buf_size)
{
const uint8 *p = buf, *p_end = buf_end;
uint32 sub_section_type;
read_uint32(p, p_end, sub_section_type);
buf = p;
switch (sub_section_type) {
case AOT_CUSTOM_SECTION_NATIVE_SYMBOL:
if (!load_native_symbol_section(buf, buf_end, module,
error_buf, error_buf_size))
goto fail;
break;
default:
break;
}
return true;
fail:
return false;
}
static void
destroy_import_memories(AOTImportMemory *import_memories,
bool is_jit_mode)
@ -1167,8 +1257,8 @@ load_text_section(const uint8 *buf, const uint8 *buf_end,
module->code = (void*)(buf + module->literal_size);
module->code_size = (uint32)(buf_end - (uint8*)module->code);
if (module->code_size > 0) {
plt_base = (uint8*)buf_end - get_plt_table_size();
if ((module->code_size > 0) && (module->native_symbol_count == 0)) {
plt_base = (uint8 *)buf_end - get_plt_table_size();
init_plt_table(plt_base);
}
return true;
@ -1920,6 +2010,13 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end,
|| !strcmp(group->section_name, ".text")
#endif
) {
if (module->native_symbol_count > 0) {
set_error_buf(error_buf, error_buf_size,
"cannot apply relocation to text section "
"for aot file generated with "
"\"--enable-indirect-mode\" flag");
goto fail;
}
if (!do_text_relocation(module, group, error_buf, error_buf_size))
goto fail;
}
@ -1993,7 +2090,8 @@ load_from_sections(AOTModule *module, AOTSection *sections,
if ((last_section_type == (uint32)-1
&& section_type != AOT_SECTION_TYPE_TARGET_INFO)
|| (last_section_type != (uint32)-1
&& section_type != last_section_type + 1)) {
&& (section_type != last_section_type + 1
&& section_type != AOT_SECTION_TYPE_CUSTOM))) {
set_error_buf(error_buf, error_buf_size,
"invalid section order");
return false;
@ -2030,6 +2128,11 @@ load_from_sections(AOTModule *module, AOTSection *sections,
error_buf, error_buf_size))
return false;
break;
case AOT_SECTION_TYPE_CUSTOM:
if (!load_custom_section(buf, buf_end, module,
error_buf, error_buf_size))
return false;
break;
default:
set_error_buf(error_buf, error_buf_size,
"invalid aot section type");
@ -2039,7 +2142,8 @@ load_from_sections(AOTModule *module, AOTSection *sections,
section = section->next;
}
if (last_section_type != AOT_SECTION_TYPE_RELOCATION) {
if (last_section_type != AOT_SECTION_TYPE_RELOCATION
&& last_section_type != AOT_SECTION_TYPE_CUSTOM) {
set_error_buf(error_buf, error_buf_size,
"section missing");
return false;
@ -2208,21 +2312,69 @@ destroy_sections(AOTSection *section_list, bool destroy_aot_text)
}
static bool
create_sections(const uint8 *buf, uint32 size,
resolve_native_symbols(const uint8 *buf, uint32 size, uint32 *p_count,
char *error_buf, uint32 error_buf_size)
{
const uint8 *p = buf, *p_end = buf + size;
uint32 section_type;
uint32 section_size = 0;
p += 8;
while (p < p_end) {
read_uint32(p, p_end, section_type);
if (section_type <= AOT_SECTION_TYPE_SIGANATURE
|| section_type == AOT_SECTION_TYPE_CUSTOM) {
read_uint32(p, p_end, section_size);
CHECK_BUF(p, p_end, section_size);
if (section_type == AOT_SECTION_TYPE_CUSTOM) {
read_uint32(p, p_end, section_type);
if (section_type == AOT_CUSTOM_SECTION_NATIVE_SYMBOL) {
/* Read the count of native symbol */
read_uint32(p, p_end, *p_count);
return true;
}
p -= sizeof(uint32);
}
}
else if (section_type > AOT_SECTION_TYPE_SIGANATURE) {
set_error_buf(error_buf, error_buf_size,
"resolve native symbol failed");
break;
}
p += section_size;
}
return true;
fail:
return false;
}
static bool
create_sections(AOTModule *module,
const uint8 *buf, uint32 size,
AOTSection **p_section_list,
char *error_buf, uint32 error_buf_size)
{
AOTSection *section_list = NULL, *section_list_end = NULL, *section;
const uint8 *p = buf, *p_end = buf + size;
bool destory_aot_text = false;
uint32 native_symbol_count = 0;
uint32 section_type;
uint32 section_size;
uint64 total_size;
uint8 *aot_text;
if (!resolve_native_symbols(buf, size, &native_symbol_count,
error_buf, error_buf_size)) {
goto fail;
}
module->native_symbol_count = native_symbol_count;
p += 8;
while (p < p_end) {
read_uint32(p, p_end, section_type);
if (section_type < AOT_SECTION_TYPE_SIGANATURE) {
if (section_type < AOT_SECTION_TYPE_SIGANATURE
|| section_type == AOT_SECTION_TYPE_CUSTOM) {
read_uint32(p, p_end, section_size);
CHECK_BUF(p, p_end, section_size);
@ -2238,7 +2390,7 @@ create_sections(const uint8 *buf, uint32 size,
section->section_body_size = section_size;
if (section_type == AOT_SECTION_TYPE_TEXT) {
if (section_size > 0) {
if ((section_size > 0) && (native_symbol_count == 0)) {
int map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE
| MMAP_PROT_EXEC;
#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
@ -2270,6 +2422,7 @@ create_sections(const uint8 *buf, uint32 size,
bh_memcpy_s(aot_text, (uint32)total_size,
section->section_body, (uint32)section_size);
section->section_body = aot_text;
destory_aot_text = true;
if ((uint32)total_size > section->section_body_size) {
memset(aot_text + (uint32)section_size,
@ -2277,8 +2430,6 @@ create_sections(const uint8 *buf, uint32 size,
section->section_body_size = (uint32)total_size;
}
}
else
section->section_body = NULL;
}
if (!section_list)
@ -2307,7 +2458,7 @@ create_sections(const uint8 *buf, uint32 size,
return true;
fail:
if (section_list)
destroy_sections(section_list, true);
destroy_sections(section_list, destory_aot_text);
return false;
}
@ -2333,14 +2484,16 @@ load(const uint8 *buf, uint32 size, AOTModule *module,
return false;
}
if (!create_sections(buf, size, &section_list, error_buf, error_buf_size))
if (!create_sections(module, buf, size, &section_list,
error_buf, error_buf_size))
return false;
ret = load_from_sections(module, section_list, error_buf, error_buf_size);
if (!ret) {
/* If load_from_sections() fails, then aot text is destroyed
in destroy_sections() */
destroy_sections(section_list, true);
destroy_sections(section_list,
module->native_symbol_count == 0 ? true : false);
/* aot_unload() won't destroy aot text again */
module->code = NULL;
}
@ -2616,6 +2769,9 @@ aot_unload(AOTModule *module)
module->mem_init_data_count,
module->is_jit_mode);
if (module->native_symbol_list)
wasm_runtime_free(module->native_symbol_list);
if (module->import_tables)
destroy_import_tables(module->import_tables,
module->is_jit_mode);
@ -2658,7 +2814,7 @@ aot_unload(AOTModule *module)
if (module->const_str_set)
bh_hash_map_destroy(module->const_str_set);
if (module->code) {
if (module->code && (module->native_symbol_count == 0)) {
/* The layout is: literal size + literal + code (with plt table) */
uint8 *mmap_addr = module->literal - sizeof(uint32);
uint32 total_size = sizeof(uint32)

View File

@ -4,6 +4,7 @@
*/
#include "aot_runtime.h"
#include "aot_intrinsic.h"
typedef struct {
const char *symbol_name;
@ -48,6 +49,40 @@ typedef struct {
#define REG_AOT_TRACE_SYM()
#endif
#define REG_INTRINSIC_SYM() \
REG_SYM(aot_intrinsic_fabs_f32), \
REG_SYM(aot_intrinsic_fabs_f64), \
REG_SYM(aot_intrinsic_floor_f32), \
REG_SYM(aot_intrinsic_floor_f64), \
REG_SYM(aot_intrinsic_ceil_f32), \
REG_SYM(aot_intrinsic_ceil_f64), \
REG_SYM(aot_intrinsic_trunc_f32), \
REG_SYM(aot_intrinsic_trunc_f64), \
REG_SYM(aot_intrinsic_rint_f32), \
REG_SYM(aot_intrinsic_rint_f64), \
REG_SYM(aot_intrinsic_sqrt_f32), \
REG_SYM(aot_intrinsic_sqrt_f64), \
REG_SYM(aot_intrinsic_copysign_f32), \
REG_SYM(aot_intrinsic_copysign_f64), \
REG_SYM(aot_intrinsic_fadd_f32), \
REG_SYM(aot_intrinsic_fadd_f64), \
REG_SYM(aot_intrinsic_fsub_f32), \
REG_SYM(aot_intrinsic_fsub_f64), \
REG_SYM(aot_intrinsic_fmul_f32), \
REG_SYM(aot_intrinsic_fmul_f64), \
REG_SYM(aot_intrinsic_fdiv_f32), \
REG_SYM(aot_intrinsic_fdiv_f64), \
REG_SYM(aot_intrinsic_fmin_f32), \
REG_SYM(aot_intrinsic_fmin_f64), \
REG_SYM(aot_intrinsic_fmax_f32), \
REG_SYM(aot_intrinsic_fmax_f64), \
REG_SYM(aot_intrinsic_clz_i32), \
REG_SYM(aot_intrinsic_clz_i64), \
REG_SYM(aot_intrinsic_ctz_i32), \
REG_SYM(aot_intrinsic_ctz_i64), \
REG_SYM(aot_intrinsic_popcnt_i32), \
REG_SYM(aot_intrinsic_popcnt_i64), \
#define REG_COMMON_SYMBOLS \
REG_SYM(aot_set_exception_with_id), \
REG_SYM(aot_invoke_native), \
@ -71,7 +106,8 @@ typedef struct {
REG_BULK_MEMORY_SYM() \
REG_ATOMIC_WAIT_SYM() \
REG_REF_TYPES_SYM() \
REG_AOT_TRACE_SYM()
REG_AOT_TRACE_SYM() \
REG_INTRINSIC_SYM() \
#define CHECK_RELOC_OFFSET(data_size) do { \
if (!check_reloc_offset(target_section_size, reloc_offset, data_size, \

View File

@ -2233,7 +2233,7 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
AOTImportFunc *import_func;
const char *signature;
void *attachment;
char buf[128];
char buf[96];
bh_assert(func_idx < aot_module->import_func_count);
@ -2282,7 +2282,7 @@ aot_call_indirect(WASMExecEnv *exec_env,
AOTImportFunc *import_func;
const char *signature = NULL;
void *attachment = NULL;
char buf[128];
char buf[96];
bool ret;
/* this function is called from native code, so exec_env->handle and

View File

@ -40,14 +40,20 @@ typedef enum AOTExceptionID {
typedef enum AOTSectionType {
AOT_SECTION_TYPE_TARGET_INFO = 0,
AOT_SECTION_TYPE_INIT_DATA,
AOT_SECTION_TYPE_TEXT,
AOT_SECTION_TYPE_FUNCTION,
AOT_SECTION_TYPE_EXPORT,
AOT_SECTION_TYPE_RELOCATION,
AOT_SECTION_TYPE_SIGANATURE
AOT_SECTION_TYPE_INIT_DATA = 1,
AOT_SECTION_TYPE_TEXT = 2,
AOT_SECTION_TYPE_FUNCTION = 3,
AOT_SECTION_TYPE_EXPORT = 4,
AOT_SECTION_TYPE_RELOCATION = 5,
AOT_SECTION_TYPE_SIGANATURE = 6,
AOT_SECTION_TYPE_CUSTOM = 100,
} AOTSectionType;
typedef enum AOTCustomSectionType {
AOT_CUSTOM_SECTION_NATIVE_SYMBOL = 1,
AOT_CUSTOM_SECTION_ACCESS_CONTROL = 2,
} AOTCustomSectionType;
typedef struct AOTObjectDataSection {
char *name;
uint8 *data;
@ -125,6 +131,10 @@ typedef struct AOTModule {
uint32 mem_init_data_count;
AOTMemInitData **mem_init_data_list;
/* native symobl */
uint32 native_symbol_count;
void **native_symbol_list;
/* import tables */
uint32 import_table_count;
AOTImportTable *import_tables;

View File

@ -0,0 +1,237 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "aot_reloc.h"
#define R_ARC_S21H_PCREL 14
#define R_ARC_S21W_PCREL 15
#define R_ARC_S25H_PCREL 16
#define R_ARC_S25W_PCREL 17
#define R_ARC_32 4
#define R_ARC_32_ME 27
void __st_r13_to_r15();
void __st_r13_to_r16();
void __st_r13_to_r17();
void __st_r13_to_r18();
void __st_r13_to_r19();
void __st_r13_to_r20();
void __st_r13_to_r21();
void __st_r13_to_r22();
void __st_r13_to_r23();
void __st_r13_to_r24();
void __st_r13_to_r25();
void __ld_r13_to_r15();
void __ld_r13_to_r16();
void __ld_r13_to_r17();
void __ld_r13_to_r18();
void __ld_r13_to_r19();
void __ld_r13_to_r20();
void __ld_r13_to_r21();
void __ld_r13_to_r22();
void __ld_r13_to_r23();
void __ld_r13_to_r24();
void __ld_r13_to_r25();
void __adddf3();
void __addsf3();
void __divdf3();
void __divdi3();
void __divsf3();
void __divsi3();
void __eqsf2();
void __extendsfdf2();
void __fixdfsi();
void __floatsidf();
void __floatsisf();
void __gedf2();
void __gtdf2();
void __ledf2();
void __lesf2();
void __ltdf2();
void __muldf3();
void __mulsf3();
void __subdf3();
void __subsf3();
void __truncdfsf2();
void __unorddf2();
static SymbolMap target_sym_map[] = {
REG_COMMON_SYMBOLS
REG_SYM(__st_r13_to_r15),
REG_SYM(__st_r13_to_r16),
REG_SYM(__st_r13_to_r17),
REG_SYM(__st_r13_to_r18),
REG_SYM(__st_r13_to_r19),
REG_SYM(__st_r13_to_r20),
REG_SYM(__st_r13_to_r21),
REG_SYM(__st_r13_to_r22),
REG_SYM(__st_r13_to_r23),
REG_SYM(__st_r13_to_r24),
REG_SYM(__st_r13_to_r25),
REG_SYM(__ld_r13_to_r15),
REG_SYM(__ld_r13_to_r16),
REG_SYM(__ld_r13_to_r17),
REG_SYM(__ld_r13_to_r18),
REG_SYM(__ld_r13_to_r19),
REG_SYM(__ld_r13_to_r20),
REG_SYM(__ld_r13_to_r21),
REG_SYM(__ld_r13_to_r22),
REG_SYM(__ld_r13_to_r23),
REG_SYM(__ld_r13_to_r24),
REG_SYM(__ld_r13_to_r25),
REG_SYM (__adddf3),
REG_SYM (__addsf3),
REG_SYM (__divdf3),
REG_SYM (__divdi3),
REG_SYM (__divsf3),
REG_SYM (__divsi3),
REG_SYM (__eqsf2),
REG_SYM (__extendsfdf2),
REG_SYM (__fixdfsi),
REG_SYM (__floatsidf),
REG_SYM (__floatsisf),
REG_SYM (__gedf2),
REG_SYM (__gtdf2),
REG_SYM (__ledf2),
REG_SYM (__lesf2),
REG_SYM (__ltdf2),
REG_SYM (__muldf3),
REG_SYM (__mulsf3),
REG_SYM (__subdf3),
REG_SYM (__subsf3),
REG_SYM (__truncdfsf2),
REG_SYM (__unorddf2),
};
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)
{
snprintf(target_buf, target_buf_size, "arc");
}
uint32
get_plt_table_size()
{
return 0;
}
void
init_plt_table(uint8 *plt)
{
(void)plt;
}
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;
}
static uint32
middle_endian_convert(uint32 insn)
{
return ((insn & 0xFFFF0000) >> 16) | ((insn & 0x0000FFFF) << 16);
}
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_ARC_S25W_PCREL:
{
uint32 insn = LOAD_I32(target_section_addr + reloc_offset);
int32 addend, value;
uintptr_t S, A, P;
CHECK_RELOC_OFFSET(sizeof(void*));
/* Convert from middle endian */
insn = middle_endian_convert(insn);
addend = ((insn << 28) >> 28) << 10;
/* Extract the next 10 bits from Position 6 to 15 in insn */
addend |= ((insn << 16) >> 22);
addend = addend << 9;
/* Extract the remaining 9 bits from Position 18 to 26 in insn */
addend |= ((insn << 5) >> 23);
/* Fill in 2 bits to get the 25 bit Offset Value */
addend = addend << 2;
/* (S + A) - P */
S = (uintptr_t)(uint8*)symbol_addr;
A = (uintptr_t)reloc_addend;
P = (uintptr_t)(target_section_addr + reloc_offset);
P &= (uintptr_t)~3;
value = (int32)(S + A + addend - P);
insn = insn & 0xf8030030;
insn |= ((((value >> 2) & 0x1ff) << 18)
| (((value >> 2) & 0x7fe00) >> 3)
| (((value >> 2) & 0x780000) >> 19));
/* Convert to middle endian */
insn = middle_endian_convert(insn);
STORE_U32(target_section_addr + reloc_offset, insn);
break;
}
case R_ARC_32:
case R_ARC_32_ME:
{
uint32 insn;
CHECK_RELOC_OFFSET(sizeof(void*));
/* (S + A) */
insn = (uint32)(uintptr_t)
((uint8*)symbol_addr + reloc_addend);
if (reloc_type == R_ARC_32_ME)
/* Convert to middle endian */
insn = middle_endian_convert(insn);
STORE_U32(target_section_addr + reloc_offset, insn);
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

@ -25,6 +25,8 @@ elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_xtensa.c)
elseif (WAMR_BUILD_TARGET MATCHES "RISCV*")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_riscv.c)
elseif (WAMR_BUILD_TARGET STREQUAL "ARC")
set (arch_source ${IWASM_AOT_DIR}/arch/aot_reloc_arc.c)
else ()
message (FATAL_ERROR "Build target isn't set")
endif ()

View File

@ -0,0 +1,69 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
.text
.align 2
#ifndef BH_PLATFORM_DARWIN
.globl invokeNative
.type invokeNative, function
invokeNative:
#else
.globl _invokeNative
_invokeNative:
#endif /* end of BH_PLATFORM_DARWIN */
/*
* Arguments passed in:
* r0: function ptr
* r1: argv
* r2: nstacks
* ARC ABI:
* r0-r7: function arguments, caller-saved
* r8-r12: temp registers, caller-saved
*/
push_s blink /* push return addr */
st.aw fp, [sp, -4] /* push fp */
mov fp, sp /* fp = sp */
mov r8, r0 /* r8 = func_ptr */
mov r9, r1 /* r9 = argv */
mov r10, r2 /* r10 = nstacks */
ld r0, [r9, 0] /* r0 = argv[0] */
ld r1, [r9, 4] /* r1 = argv[1] */
ld r2, [r9, 8] /* r2 = argv[2] */
ld r3, [r9, 12] /* r3 = argv[3] */
ld r4, [r9, 16] /* r4 = argv[4] */
ld r5, [r9, 20] /* r5 = argv[5] */
ld r6, [r9, 24] /* r6 = argv[6] */
ld r7, [r9, 28] /* r7 = argv[7] */
add r9, r9, 32 /* r9 = stack_args */
breq r10, 0, call_func /* if (r10 == 0) goto call_func */
asl r11, r10, 2 /* r11 = nstacks * 4 */
sub sp, sp, r11 /* sp = sp - nstacks * 4 */
and sp, sp, ~7 /* make sp 8-byte aligned */
mov r11, sp /* r11 = sp */
loop_stack_args:
breq r10, 0, call_func /* if (r10 == 0) goto call_func */
ld r12, [r9] /* r12 = stack_args[i] */
st r12, [r11] /* stack[i] = r12 */
add r9, r9, 4 /* r9 = r9 + 4 */
add r11, r11, 4 /* r11 = r11 + 4 */
sub r10, r10, 1 /* r10 = r10 + 1 */
j loop_stack_args
call_func:
jl [r8] /* call function */
mov sp, fp /* sp = fp */
ld.ab fp, [sp, 4] /* pop fp */
pop_s blink /* pop return addr */
j_s [blink] /* ret */
nop_s

View File

@ -68,6 +68,8 @@ elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_xtensa.s)
elseif (WAMR_BUILD_TARGET MATCHES "RISCV*")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv.S)
elseif (WAMR_BUILD_TARGET STREQUAL "ARC")
set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arc.s)
else ()
message (FATAL_ERROR "Build target isn't set")
endif ()

View File

@ -12,6 +12,10 @@
#include "../aot/aot_runtime.h"
#endif
#if WASM_ENABLE_AOT != 0
#include "aot_runtime.h"
#endif
#if WASM_ENABLE_THREAD_MGR != 0
#include "../libraries/thread-mgr/thread_manager.h"
#endif
@ -50,6 +54,14 @@ wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
exec_env->wasm_stack.s.bottom + stack_size;
exec_env->wasm_stack.s.top = exec_env->wasm_stack.s.bottom;
#if WASM_ENABLE_AOT != 0
if (module_inst->module_type == Wasm_Module_AoT) {
AOTModuleInstance *i = (AOTModuleInstance *)module_inst;
AOTModule *m = (AOTModule *)i->aot_module.ptr;
exec_env->native_symbol = m->native_symbol_list;
}
#endif
#if WASM_ENABLE_MEMORY_TRACING != 0
wasm_runtime_dump_exec_env_mem_consumption(exec_env);
#endif

View File

@ -2480,7 +2480,8 @@ fail:
#if defined(BUILD_TARGET_ARM_VFP) \
|| defined(BUILD_TARGET_THUMB_VFP) \
|| defined(BUILD_TARGET_RISCV32_ILP32D) \
|| defined(BUILD_TARGET_RISCV32_ILP32)
|| defined(BUILD_TARGET_RISCV32_ILP32) \
|| defined(BUILD_TARGET_ARC)
typedef void (*GenericFunctionPointer)();
int64 invokeNative(GenericFunctionPointer f, uint32 *args, uint32 n_stacks);
@ -2496,8 +2497,7 @@ static Int64FuncPtr invokeNative_Int64 = (Int64FuncPtr)(uintptr_t)invokeNative;
static Int32FuncPtr invokeNative_Int32 = (Int32FuncPtr)(uintptr_t)invokeNative;
static VoidFuncPtr invokeNative_Void = (VoidFuncPtr)(uintptr_t)invokeNative;
#if !defined(BUILD_TARGET_RISCV32_ILP32D) \
&& !defined(BUILD_TARGET_RISCV32_ILP32)
#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP)
#define MAX_REG_INTS 4
#define MAX_REG_FLOATS 16
#else
@ -2519,7 +2519,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
uint32 result_count = func_type->result_count;
uint32 ext_ret_count = result_count > 1 ? result_count - 1 : 0;
bool ret = false;
#if !defined(BUILD_TARGET_RISCV32_ILP32)
#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC)
uint32 *fps;
int n_fps = 0;
#else
@ -2544,14 +2544,15 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
break;
case VALUE_TYPE_I64:
if (n_ints < MAX_REG_INTS - 1) {
#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_RISCV32_ILP32D)
#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP)
/* 64-bit data must be 8 bytes aligned in arm */
if (n_ints & 1)
n_ints++;
#endif
n_ints += 2;
}
#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_RISCV32_ILP32D)
#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_RISCV32_ILP32D) \
|| defined(BUILD_TARGET_ARC)
/* part in register, part in stack */
else if (n_ints == MAX_REG_INTS - 1) {
n_ints++;
@ -2561,8 +2562,10 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
else {
/* 64-bit data in stack must be 8 bytes aligned
in arm and riscv32 */
#if !defined(BUILD_TARGET_ARC)
if (n_stacks & 1)
n_stacks++;
#endif
n_stacks += 2;
}
break;
@ -2575,23 +2578,26 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
break;
case VALUE_TYPE_F64:
if (n_fps < MAX_REG_FLOATS - 1) {
#if !defined(BUILD_TARGET_RISCV32_ILP32)
#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC)
/* 64-bit data must be 8 bytes aligned in arm */
if (n_fps & 1)
n_fps++;
#endif
n_fps += 2;
}
#if defined(BUILD_TARGET_RISCV32_ILP32)
#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC)
else if (n_fps == MAX_REG_FLOATS - 1) {
n_fps++;
n_stacks++;
}
#endif
else {
/* 64-bit data must be 8 bytes aligned in arm */
/* 64-bit data in stack must be 8 bytes aligned
in arm and riscv32 */
#if !defined(BUILD_TARGET_ARC)
if (n_stacks & 1)
n_stacks++;
#endif
n_stacks += 2;
}
break;
@ -2634,11 +2640,11 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
n_stacks++;
}
#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_RISCV32_ILP32D)
#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP)
argc1 = MAX_REG_INTS + MAX_REG_FLOATS + n_stacks;
#elif defined(BUILD_TARGET_RISCV32_ILP32)
#elif defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC)
argc1 = MAX_REG_INTS + n_stacks;
#else
#else /* for BUILD_TARGET_RISCV32_ILP32D */
argc1 = MAX_REG_INTS + MAX_REG_FLOATS * 2 + n_stacks;
#endif
@ -2651,12 +2657,12 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
}
ints = argv1;
#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_RISCV32_ILP32D)
#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP)
fps = ints + MAX_REG_INTS;
stacks = fps + MAX_REG_FLOATS;
#elif defined(BUILD_TARGET_RISCV32_ILP32)
#elif defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC)
stacks = ints + MAX_REG_INTS;
#else
#else /* for BUILD_TARGET_RISCV32_ILP32D */
fps = ints + MAX_REG_INTS;
stacks = fps + MAX_REG_FLOATS * 2;
#endif
@ -2719,16 +2725,16 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_I64:
{
if (n_ints < MAX_REG_INTS - 1) {
#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_RISCV32_ILP32D)
#if defined(BUILD_TARGET_ARM_VFP) || defined(BUILD_TARGET_THUMB_VFP)
/* 64-bit data must be 8 bytes aligned in arm */
if (n_ints & 1)
n_ints++;
#endif
*(uint64*)&ints[n_ints] = *(uint64*)argv_src;
n_ints += 2;
argv_src += 2;
ints[n_ints++] = *argv_src++;
ints[n_ints++] = *argv_src++;
}
#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_RISCV32_ILP32D)
#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_RISCV32_ILP32D) \
|| defined(BUILD_TARGET_ARC)
else if (n_ints == MAX_REG_INTS - 1) {
ints[n_ints++] = *argv_src++;
stacks[n_stacks++] = *argv_src++;
@ -2737,11 +2743,12 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
else {
/* 64-bit data in stack must be 8 bytes aligned
in arm and riscv32 */
#if !defined(BUILD_TARGET_ARC)
if (n_stacks & 1)
n_stacks++;
*(uint64*)&stacks[n_stacks] = *(uint64*)argv_src;
n_stacks += 2;
argv_src += 2;
#endif
stacks[n_stacks++] = *argv_src++;
stacks[n_stacks++] = *argv_src++;
}
break;
}
@ -2757,28 +2764,29 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_F64:
{
if (n_fps < MAX_REG_FLOATS - 1) {
#if !defined(BUILD_TARGET_RISCV32_ILP32)
#if !defined(BUILD_TARGET_RISCV32_ILP32) && !defined(BUILD_TARGET_ARC)
/* 64-bit data must be 8 bytes aligned in arm */
if (n_fps & 1)
n_fps++;
#endif
*(float64*)&fps[n_fps] = *(float64*)argv_src;
n_fps += 2;
argv_src += 2;
fps[n_fps++] = *argv_src++;
fps[n_fps++] = *argv_src++;
}
#if defined(BUILD_TARGET_RISCV32_ILP32)
#if defined(BUILD_TARGET_RISCV32_ILP32) || defined(BUILD_TARGET_ARC)
else if (n_fps == MAX_REG_FLOATS - 1) {
fps[n_fps++] = *argv_src++;
stacks[n_stacks++] = *argv_src++;
}
#endif
else {
/* 64-bit data must be 8 bytes aligned in arm */
/* 64-bit data in stack must be 8 bytes aligned
in arm and riscv32 */
#if !defined(BUILD_TARGET_ARC)
if (n_stacks & 1)
n_stacks++;
*(float64*)&stacks[n_stacks] = *(float64*)argv_src;
n_stacks += 2;
argv_src += 2;
#endif
stacks[n_stacks++] = *argv_src++;
stacks[n_stacks++] = *argv_src++;
}
break;
}
@ -2885,7 +2893,8 @@ fail:
#endif /* end of defined(BUILD_TARGET_ARM_VFP)
|| defined(BUILD_TARGET_THUMB_VFP) \
|| defined(BUILD_TARGET_RISCV32_ILP32D)
|| defined(BUILD_TARGET_RISCV32_ILP32) */
|| defined(BUILD_TARGET_RISCV32_ILP32)
|| defined(BUILD_TARGET_ARC) */
#if defined(BUILD_TARGET_X86_32) \
|| defined(BUILD_TARGET_ARM) \

View File

@ -229,6 +229,12 @@ typedef struct AOTCompData {
WASMModule *wasm_module;
} AOTCompData;
typedef struct AOTNativeSymbol {
bh_list_link link;
const char *symbol;
int32 index;
} AOTNativeSymbol;
AOTCompData*
aot_create_comp_data(WASMModule *module);

View File

@ -2111,19 +2111,26 @@ bool
aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
{
char *err = NULL;
LLVMCodeGenFileType file_type = LLVMObjectFile;
LLVMTargetRef target =
LLVMGetTargetMachineTarget(comp_ctx->target_machine);
bh_print_time("Begin to emit object file");
if (!strncmp(LLVMGetTargetName(target), "arc", 3))
/* Emit to assmelby file instead for arc target
as it cannot emit to object file */
file_type = LLVMAssemblyFile;
if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
comp_ctx->module,
file_name,
LLVMObjectFile,
file_name, file_type,
&err) != 0) {
if (err) {
LLVMDisposeMessage(err);
err = NULL;
}
aot_set_last_error("emit elf to memory buffer failed.");
aot_set_last_error("emit elf to object file failed.");
return false;
}

View File

@ -790,6 +790,23 @@ get_relocation_section_size(AOTObjectData *obj_data)
is_32bit_binary(obj_data->binary));
}
static uint32
get_native_symbol_list_size(AOTCompContext *comp_ctx)
{
uint32 len = 0;
AOTNativeSymbol *sym = NULL;
sym = bh_list_first_elem(&comp_ctx->native_symbols);
while (sym) {
len = align_uint(len, 2);
len += get_string_size(sym->symbol);
sym = bh_list_elem_next(sym);
}
return len;
}
static uint32
get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
AOTObjectData *obj_data)
@ -835,6 +852,14 @@ get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
size += (uint32)sizeof(uint32) * 2;
size += get_relocation_section_size(obj_data);
if (get_native_symbol_list_size(comp_ctx) > 0) {
/* emit only when threre are native symbols */
size = align_uint(size, 4);
/* section id + section size + sub section id + symbol count */
size += (uint32)sizeof(uint32) * 4;
size += get_native_symbol_list_size(comp_ctx);
}
return size;
}
@ -1505,6 +1530,38 @@ aot_emit_relocation_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
return true;
}
static bool
aot_emit_native_symbol(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
AOTCompContext *comp_ctx)
{
uint32 offset = *p_offset;
AOTNativeSymbol *sym = NULL;
if (bh_list_length(&comp_ctx->native_symbols) == 0)
/* emit only when threre are native symbols */
return true;
*p_offset = offset = align_uint(offset, 4);
EMIT_U32(AOT_SECTION_TYPE_CUSTOM);
/* sub section id + symbol count + symbol list */
EMIT_U32(sizeof(uint32) * 2 + get_native_symbol_list_size(comp_ctx));
EMIT_U32(AOT_CUSTOM_SECTION_NATIVE_SYMBOL);
EMIT_U32(bh_list_length(&comp_ctx->native_symbols));
sym = bh_list_first_elem(&comp_ctx->native_symbols);
while (sym) {
offset = align_uint(offset, 2);
EMIT_STR(sym->symbol);
sym = bh_list_elem_next(sym);
}
*p_offset = offset;
return true;
}
typedef uint32 U32;
typedef int32 I32;
typedef uint16 U16;
@ -2164,6 +2221,8 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
{
char *err = NULL;
AOTObjectData *obj_data;
LLVMTargetRef target =
LLVMGetTargetMachineTarget(comp_ctx->target_machine);
bh_print_time("Begin to emit object file to buffer");
@ -2173,11 +2232,76 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
}
memset(obj_data, 0, sizeof(AOTObjectData));
if (LLVMTargetMachineEmitToMemoryBuffer(comp_ctx->target_machine,
comp_ctx->module,
LLVMObjectFile,
&err,
&obj_data->mem_buf) != 0) {
bh_print_time("Begin to emit object file");
if (!strncmp(LLVMGetTargetName(target), "arc", 3)) {
/* Emit to assmelby file instead for arc target
as it cannot emit to object file */
char file_name[] = "wasm-XXXXXX", buf[128];
int fd, ret;
if ((fd = mkstemp(file_name)) <= 0) {
aot_set_last_error("make temp file failed.");
goto fail;
}
/* close and remove temp file */
close(fd);
unlink(file_name);
snprintf(buf, sizeof(buf), "%s%s", file_name, ".s");
if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
comp_ctx->module,
buf, LLVMAssemblyFile,
&err) != 0) {
if (err) {
LLVMDisposeMessage(err);
err = NULL;
}
aot_set_last_error("emit elf to object file failed.");
goto fail;
}
/* call arc gcc to compile assembly file to object file */
/* TODO: get arc gcc from environment variable firstly
and check whether the toolchain exists actually */
snprintf(buf, sizeof(buf), "%s%s%s%s%s%s",
"/opt/zephyr-sdk/arc-zephyr-elf/bin/arc-zephyr-elf-gcc ",
"-mcpu=arcem -o ", file_name, ".o -c ", file_name, ".s");
/* TODO: use try..catch to handle possible exceptions */
ret = system(buf);
/* remove temp assembly file */
snprintf(buf, sizeof(buf), "%s%s", file_name, ".s");
unlink(buf);
if (ret != 0) {
aot_set_last_error("failed to compile asm file to obj file "
"with arc gcc toolchain.");
goto fail;
}
/* create memory buffer from object file */
snprintf(buf, sizeof(buf), "%s%s", file_name, ".o");
ret = LLVMCreateMemoryBufferWithContentsOfFile(buf,
&obj_data->mem_buf,
&err);
/* remove temp object file */
snprintf(buf, sizeof(buf), "%s%s",file_name, ".o");
unlink(buf);
if (ret != 0) {
if (err) {
LLVMDisposeMessage(err);
err = NULL;
}
aot_set_last_error("create mem buffer with file failed.");
goto fail;
}
}
else if (LLVMTargetMachineEmitToMemoryBuffer(comp_ctx->target_machine,
comp_ctx->module,
LLVMObjectFile, &err,
&obj_data->mem_buf) != 0) {
if (err) {
LLVMDisposeMessage(err);
err = NULL;
@ -2242,7 +2366,8 @@ aot_emit_aot_file_buf(AOTCompContext *comp_ctx,
|| !aot_emit_text_section(buf, buf_end, &offset, comp_data, obj_data)
|| !aot_emit_func_section(buf, buf_end, &offset, comp_data, obj_data)
|| !aot_emit_export_section(buf, buf_end, &offset, comp_data, obj_data)
|| !aot_emit_relocation_section(buf, buf_end, &offset, comp_data, obj_data))
|| !aot_emit_relocation_section(buf, buf_end, &offset, comp_data, obj_data)
|| !aot_emit_native_symbol(buf, buf_end, &offset, comp_ctx))
goto fail2;
#if 0

View File

@ -68,6 +68,24 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return false;
}
}
else if (comp_ctx->is_indirect_mode) {
int32 func_index;
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
aot_set_last_error("create LLVM function type failed.");
return false;
}
func_index = aot_get_native_symbol_index(
comp_ctx, "aot_set_exception_with_id");
if (func_index < 0) {
return false;
}
if (!(func =
aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
func_ptr_type, func_index))) {
return false;
}
}
else {
/* Create LLVM function with external function pointer */
if (!(func = LLVMGetNamedFunction(comp_ctx->module,

View File

@ -168,10 +168,26 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return false;
}
}
else if (comp_ctx->is_indirect_mode) {
int32 func_index;
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
aot_set_last_error("create LLVM function type failed.");
return false;
}
func_index =
aot_get_native_symbol_index(comp_ctx, func_name);
if (func_index < 0) {
return false;
}
if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
func_ptr_type, func_index))) {
return false;
}
}
else {
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
&& !(func = LLVMAddFunction(comp_ctx->module,
func_name, func_type))) {
&& !(func =
LLVMAddFunction(comp_ctx->module, func_name, func_type))) {
aot_set_last_error("add LLVM function failed.");
return false;
}
@ -547,7 +563,22 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
goto fail;
}
else {
func = func_ctxes[func_idx - import_func_count]->func;
if (comp_ctx->is_indirect_mode) {
LLVMTypeRef func_ptr_type;
if (!(func_ptr_type = LLVMPointerType(
func_ctxes[func_idx - import_func_count]->func_type, 0))) {
aot_set_last_error("construct func ptr type failed.");
goto fail;
}
if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->func_ptrs,
func_ptr_type, func_idx))) {
goto fail;
}
}
else {
func = func_ctxes[func_idx - import_func_count]->func;
}
aot_func = func_ctxes[func_idx - import_func_count]->aot_func;
callee_cell_num = aot_func->param_cell_num + aot_func->local_cell_num + 1;
@ -650,6 +681,22 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return false;
}
}
else if (comp_ctx->is_indirect_mode) {
int32 func_index;
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
aot_set_last_error("create LLVM function type failed.");
return false;
}
func_index =
aot_get_native_symbol_index(comp_ctx, func_name);
if (func_index < 0) {
return false;
}
if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
func_ptr_type, func_index))) {
return false;
}
}
else {
if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
&& !(func = LLVMAddFunction(comp_ctx->module,

View File

@ -651,6 +651,7 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
LLVMValueRef mem_size = get_memory_curr_page_count(comp_ctx, func_ctx);
LLVMValueRef delta, param_values[2], ret_value, func, value;
LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
int32 func_index;
if (!mem_size)
return false;
@ -679,6 +680,21 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
return false;
}
}
else if (comp_ctx->is_indirect_mode) {
if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
aot_set_last_error("create LLVM function type failed.");
return false;
}
func_index =
aot_get_native_symbol_index(comp_ctx, "aot_enlarge_memory");
if (func_index < 0) {
return false;
}
if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
func_ptr_type, func_index))) {
return false;
}
}
else {
char *func_name = "aot_enlarge_memory";
/* AOT mode, delcare the function */
@ -715,7 +731,6 @@ fail:
return false;
}
#if WASM_ENABLE_BULK_MEMORY != 0
static LLVMValueRef
@ -924,6 +939,8 @@ aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len)))
return false;
/* TODO: lookup func ptr of "memmove" to call for XIP mode */
if (!(res = LLVMBuildMemMove(comp_ctx->builder, dst_addr, 1,
src_addr, 1, len))) {
aot_set_last_error("llvm build memmove failed.");
@ -947,7 +964,13 @@ aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len)))
return false;
val = LLVMBuildIntCast2(comp_ctx->builder, val, INT8_TYPE, true, "mem_set_value");
if (!(val = LLVMBuildIntCast2(comp_ctx->builder, val, INT8_TYPE,
true, "mem_set_value"))) {
aot_set_last_error("llvm build int cast2 failed.");
return false;
}
/* TODO: lookup func ptr of "memset" to call for XIP mode */
if (!(res = LLVMBuildMemSet(comp_ctx->builder, dst_addr,
val, len, 1))) {

View File

@ -7,6 +7,7 @@
#include "aot_emit_exception.h"
#include "aot_emit_control.h"
#include "../aot/aot_runtime.h"
#include "../aot/aot_intrinsic.h"
#include <stdarg.h>
@ -138,6 +139,7 @@
/* Call llvm constrained floating-point intrinsic */
static LLVMValueRef
call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx,
bool is_f32,
const char *intrinsic,
...)
@ -145,14 +147,18 @@ call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
va_list param_value_list;
LLVMValueRef ret;
LLVMTypeRef param_types[4], ret_type = is_f32 ? F32_TYPE : F64_TYPE;
int param_count = ((comp_ctx->disable_llvm_intrinsics == false)
|| aot_intrinsic_check_capability(comp_ctx, intrinsic))
? 4 : 2;
param_types[0] = param_types[1] = ret_type;
param_types[2] = param_types[3] = MD_TYPE;
va_start(param_value_list, intrinsic);
ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, param_types,
4, param_value_list);
ret =
aot_call_llvm_intrinsic_v(comp_ctx, func_ctx, intrinsic, ret_type,
param_types, param_count, param_value_list);
va_end(param_value_list);
@ -162,6 +168,7 @@ call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
/* Call llvm constrained libm-equivalent intrinsic */
static LLVMValueRef
call_llvm_libm_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx,
bool is_f32,
const char *intrinsic,
...)
@ -175,7 +182,7 @@ call_llvm_libm_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
va_start(param_value_list, intrinsic);
ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, param_types,
ret = aot_call_llvm_intrinsic_v(comp_ctx, func_ctx, intrinsic, ret_type, param_types,
3, param_value_list);
va_end(param_value_list);
@ -185,6 +192,7 @@ call_llvm_libm_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
static LLVMValueRef
compile_op_float_min_max(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx,
bool is_f32,
LLVMValueRef left,
LLVMValueRef right,
@ -230,8 +238,9 @@ compile_op_float_min_max(AOTCompContext *comp_ctx,
return NULL;
}
if (!(cmp = aot_call_llvm_intrinsic(comp_ctx, intrinsic, ret_type,
param_types, 2, left, right)))
if (!(cmp =
aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, ret_type,
param_types, 2, left, right)))
return NULL;
if (!(cmp = LLVMBuildSelect(comp_ctx->builder,
@ -266,13 +275,14 @@ typedef enum BitCountType {
POP_CNT64
} BitCountType;
static char *bit_cnt_llvm_intrinsic[] = { "llvm.ctlz.i32",
"llvm.ctlz.i64",
"llvm.cttz.i32",
"llvm.cttz.i64",
"llvm.ctpop.i32",
"llvm.ctpop.i64",
};
static char *bit_cnt_llvm_intrinsic[] = {
"llvm.ctlz.i32",
"llvm.ctlz.i64",
"llvm.cttz.i32",
"llvm.cttz.i64",
"llvm.ctpop.i32",
"llvm.ctpop.i64",
};
static bool
aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
@ -290,6 +300,7 @@ aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
/* Call the LLVM intrinsic function */
if (type < POP_CNT32)
DEF_INT_UNARY_OP(aot_call_llvm_intrinsic(comp_ctx,
func_ctx,
bit_cnt_llvm_intrinsic[type],
ret_type,
param_types,
@ -299,6 +310,7 @@ aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
NULL);
else
DEF_INT_UNARY_OP(aot_call_llvm_intrinsic(comp_ctx,
func_ctx,
bit_cnt_llvm_intrinsic[type],
ret_type,
param_types,
@ -823,6 +835,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
else
DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
comp_ctx,
func_ctx,
is_f32,
(is_f32
? "llvm.experimental.constrained.fadd.f32"
@ -840,6 +853,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
else
DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
comp_ctx,
func_ctx,
is_f32,
(is_f32
? "llvm.experimental.constrained.fsub.f32"
@ -857,6 +871,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
else
DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
comp_ctx,
func_ctx,
is_f32,
(is_f32
? "llvm.experimental.constrained.fmul.f32"
@ -874,6 +889,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
else
DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
comp_ctx,
func_ctx,
is_f32,
(is_f32
? "llvm.experimental.constrained.fdiv.f32"
@ -886,6 +902,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return true;
case FLOAT_MIN:
DEF_FP_BINARY_OP(compile_op_float_min_max(comp_ctx,
func_ctx,
is_f32,
left,
right,
@ -894,6 +911,7 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return true;
case FLOAT_MAX:
DEF_FP_BINARY_OP(compile_op_float_min_max(comp_ctx,
func_ctx,
is_f32,
left,
right,
@ -912,6 +930,7 @@ fail:
static LLVMValueRef
call_llvm_float_math_intrinsic(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx,
bool is_f32,
const char *intrinsic,
...)
@ -924,8 +943,8 @@ call_llvm_float_math_intrinsic(AOTCompContext *comp_ctx,
va_start(param_value_list, intrinsic);
ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, &param_type,
1, param_value_list);
ret = aot_call_llvm_intrinsic_v(comp_ctx, func_ctx, intrinsic, ret_type,
&param_type, 1, param_value_list);
va_end(param_value_list);
@ -939,6 +958,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
switch (math_op) {
case FLOAT_ABS:
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
func_ctx,
is_f32,
is_f32 ? "llvm.fabs.f32" :
"llvm.fabs.f64",
@ -952,6 +972,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
case FLOAT_CEIL:
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
func_ctx,
is_f32,
is_f32 ? "llvm.ceil.f32" :
"llvm.ceil.f64",
@ -960,6 +981,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return true;
case FLOAT_FLOOR:
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
func_ctx,
is_f32,
is_f32 ? "llvm.floor.f32":
"llvm.floor.f64",
@ -968,6 +990,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return true;
case FLOAT_TRUNC:
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
func_ctx,
is_f32,
is_f32 ? "llvm.trunc.f32" :
"llvm.trunc.f64",
@ -976,6 +999,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return true;
case FLOAT_NEAREST:
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
func_ctx,
is_f32,
is_f32 ? "llvm.rint.f32" :
"llvm.rint.f64",
@ -983,8 +1007,10 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
NULL);
return true;
case FLOAT_SQRT:
if (is_targeting_soft_float(comp_ctx, is_f32))
if (is_targeting_soft_float(comp_ctx, is_f32)
|| comp_ctx->disable_llvm_intrinsics)
DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
func_ctx,
is_f32,
is_f32 ? "llvm.sqrt.f32" :
"llvm.sqrt.f64",
@ -993,6 +1019,7 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
else
DEF_FP_UNARY_OP(call_llvm_libm_experimental_constrained_intrinsic(
comp_ctx,
func_ctx,
is_f32,
(is_f32
? "llvm.experimental.constrained.sqrt.f32"
@ -1022,6 +1049,7 @@ compile_float_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
param_types[0] = param_types[1] = ret_type = is_f32 ? F32_TYPE : F64_TYPE;
DEF_FP_BINARY_OP(aot_call_llvm_intrinsic(comp_ctx,
func_ctx,
is_f32 ? "llvm.copysign.f32" :
"llvm.copysign.f64",
ret_type,

View File

@ -7,7 +7,7 @@
#include "aot_compiler.h"
#include "aot_emit_exception.h"
#include "../aot/aot_runtime.h"
#include "../aot/aot_intrinsic.h"
LLVMTypeRef
wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type)
@ -38,7 +38,7 @@ wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type)
*/
static LLVMValueRef
aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type,
uint32 func_index)
uint32 func_index, LLVMTypeRef *p_func_type)
{
LLVMValueRef func = NULL;
LLVMTypeRef *param_types, ret_type, func_type;
@ -107,6 +107,9 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, AOTFuncType *aot_func_type,
LLVMSetValueName(local_value, "");
}
if (p_func_type)
*p_func_type = func_type;
fail:
wasm_runtime_free(param_types);
return func;
@ -604,6 +607,7 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
LLVMValueRef stack_bound_offset = I32_FOUR, stack_bound_addr;
LLVMValueRef aux_stack_bound_offset = I32_SIX, aux_stack_bound_addr;
LLVMValueRef aux_stack_bottom_offset = I32_SEVEN, aux_stack_bottom_addr;
LLVMValueRef native_symbol_offset = I32_EIGHT, native_symbol_addr;
char local_name[32];
uint64 size;
uint32 i, j = 0;
@ -621,7 +625,8 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
func_ctx->aot_func = func;
/* Add LLVM function */
if (!(func_ctx->func = aot_add_llvm_func(comp_ctx, aot_func_type, func_index)))
if (!(func_ctx->func = aot_add_llvm_func(comp_ctx, aot_func_type,
func_index, &func_ctx->func_type)))
goto fail;
/* Create function's first AOTBlock */
@ -741,6 +746,27 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
goto fail;
}
if (!(native_symbol_addr =
LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
&native_symbol_offset, 1, "native_symbol_addr"))) {
aot_set_last_error("llvm build in bounds gep failed");
goto fail;
}
if (!(func_ctx->native_symbol =
LLVMBuildLoad(comp_ctx->builder, native_symbol_addr,
"native_symbol_tmp"))) {
aot_set_last_error("llvm build bit cast failed");
goto fail;
}
if (!(func_ctx->native_symbol =
LLVMBuildBitCast(comp_ctx->builder, func_ctx->native_symbol,
comp_ctx->exec_env_type, "native_symbol"))) {
aot_set_last_error("llvm build bit cast failed");
goto fail;
}
for (i = 0; i < aot_func_type->param_count; i++, j++) {
snprintf(local_name, sizeof(local_name), "l%d", i);
func_ctx->locals[i] =
@ -814,7 +840,7 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
}
else {
if (!(func_ctx->last_alloca = LLVMBuildAlloca(comp_ctx->builder, INT8_TYPE,
"stack_ptr"))) {
"stack_ptr"))) {
aot_set_last_error("llvm build alloca failed.");
goto fail;
}
@ -1089,7 +1115,8 @@ static ArchItem valid_archs[] = {
{ "thumbv8m.main", true },
{ "thumbv8.1m.main", true },
{ "riscv32", true},
{ "riscv64", true}
{ "riscv64", true},
{ "arc", true }
};
static const char *valid_abis[] = {
@ -1230,6 +1257,10 @@ aot_create_comp_context(AOTCompData *comp_data,
goto fail;
}
if (BH_LIST_ERROR == bh_list_init(&comp_ctx->native_symbols)) {
goto fail;
}
if (option->enable_bulk_memory)
comp_ctx->enable_bulk_memory = true;
@ -1248,6 +1279,12 @@ aot_create_comp_context(AOTCompData *comp_data,
if (option->enable_aux_stack_check)
comp_ctx->enable_aux_stack_check = true;
if (option->is_indirect_mode)
comp_ctx->is_indirect_mode = true;
if (option->disable_llvm_intrinsics)
comp_ctx->disable_llvm_intrinsics = true;
if (option->is_jit_mode) {
char *triple_jit = NULL;
@ -1496,7 +1533,12 @@ aot_create_comp_context(AOTCompData *comp_data,
goto fail;
}
if (!LLVMTargetHasAsmBackend(target)) {
/* Report error if target isn't arc and hasn't asm backend.
For arc target, as it cannot emit to memory buffer of elf file currently,
we let it emit to assembly file instead, and then call arc-gcc to compile
asm file to elf file, and read elf file to memory buffer. */
if (strncmp(comp_ctx->target_arch, "arc", 3)
&& !LLVMTargetHasAsmBackend(target)) {
snprintf(buf, sizeof(buf),
"no asm backend for this target (%s).", LLVMGetTargetName(target));
aot_set_last_error(buf);
@ -1631,6 +1673,18 @@ aot_create_comp_context(AOTCompData *comp_data,
aot_create_func_contexts(comp_data, comp_ctx)))
goto fail;
if (cpu) {
int len = strlen(cpu) + 1;
if (!(comp_ctx->target_cpu = wasm_runtime_malloc(len))) {
aot_set_last_error("allocate memory failed");
goto fail;
}
bh_memcpy_s(comp_ctx->target_cpu, len, cpu, len);
}
if (comp_ctx->disable_llvm_intrinsics)
aot_intrinsic_fill_capability_flags(comp_ctx);
ret = comp_ctx;
fail:
@ -1676,9 +1730,65 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx)
aot_destroy_func_contexts(comp_ctx->func_ctxes,
comp_ctx->func_ctx_count);
if (bh_list_length(&comp_ctx->native_symbols) > 0) {
AOTNativeSymbol *sym = bh_list_first_elem(&comp_ctx->native_symbols);
while (sym) {
AOTNativeSymbol *t = bh_list_elem_next(sym);
bh_list_remove(&comp_ctx->native_symbols, sym);
wasm_runtime_free(sym);
sym = t;
}
}
if (comp_ctx->target_cpu) {
wasm_runtime_free(comp_ctx->target_cpu);
}
wasm_runtime_free(comp_ctx);
}
int32
aot_get_native_symbol_index(AOTCompContext *comp_ctx, const char *symbol)
{
int32 idx = -1;
AOTNativeSymbol *sym = NULL;
sym = bh_list_first_elem(&comp_ctx->native_symbols);
/* Lookup an existing symobl record */
while (sym) {
if (strcmp(sym->symbol, symbol) == 0) {
idx = sym->index;
break;
}
sym = bh_list_elem_next(sym);
}
/* Given symbol is not exist in list, then we alloc a new index for it */
if (idx < 0) {
sym = wasm_runtime_malloc(sizeof(AOTNativeSymbol));
if (!sym) {
aot_set_last_error("alloc native symbol failed.");
return idx;
}
idx = bh_list_length(&comp_ctx->native_symbols);
sym->symbol = symbol;
sym->index = idx;
if (BH_LIST_ERROR == bh_list_insert(&comp_ctx->native_symbols, sym)) {
wasm_runtime_free(sym);
aot_set_last_error("alloc index for native symbol failed.");
return -1;
}
}
return idx;
}
void
aot_value_stack_push(AOTValueStack *stack, AOTValue *value)
{
@ -1901,6 +2011,7 @@ aot_build_zero_function_ret(AOTCompContext *comp_ctx,
static LLVMValueRef
__call_llvm_intrinsic(const AOTCompContext *comp_ctx,
const AOTFuncContext *func_ctx,
const char *name,
LLVMTypeRef ret_type,
LLVMTypeRef *param_types,
@ -1909,25 +2020,67 @@ __call_llvm_intrinsic(const AOTCompContext *comp_ctx,
{
LLVMValueRef func, ret;
LLVMTypeRef func_type;
const char *symname;
int32 func_idx;
/* Declare llvm intrinsic function if necessary */
if (!(func = LLVMGetNamedFunction(comp_ctx->module, name))) {
if (!(func_type = LLVMFunctionType(ret_type, param_types,
(uint32)param_count, false))) {
aot_set_last_error("create LLVM function type failed.");
if (comp_ctx->disable_llvm_intrinsics
&& (aot_intrinsic_check_capability(comp_ctx, name) == false)) {
if (func_ctx == NULL) {
aot_set_last_error_v("invalid func_ctx for intrinsic: %s", name);
return NULL;
}
if (!(func = LLVMAddFunction(comp_ctx->module, name, func_type))) {
aot_set_last_error("add LLVM function failed.");
if (!(func_type = LLVMFunctionType(ret_type, param_types,
(uint32)param_count, false))) {
aot_set_last_error("create LLVM intrinsic function type failed.");
return NULL;
}
if (!(func_type = LLVMPointerType(func_type, 0))) {
aot_set_last_error(
"create LLVM intrinsic function pointer type failed.");
return NULL;
}
if (!(symname = aot_intrinsic_get_symbol(name))) {
aot_set_last_error_v("runtime intrinsic not implemented: %s\n",
name);
return NULL;
}
func_idx =
aot_get_native_symbol_index((AOTCompContext *)comp_ctx, symname);
if (func_idx < 0) {
aot_set_last_error_v("get runtime intrinsc index failed: %s\n",
name);
return NULL;
}
if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
func_type, func_idx))) {
aot_set_last_error_v("get runtime intrinsc failed: %s\n", name);
return NULL;
}
}
else {
/* Declare llvm intrinsic function if necessary */
if (!(func = LLVMGetNamedFunction(comp_ctx->module, name))) {
if (!(func_type = LLVMFunctionType(ret_type, param_types,
(uint32)param_count, false))) {
aot_set_last_error("create LLVM intrinsic function type failed.");
return NULL;
}
if (!(func = LLVMAddFunction(comp_ctx->module, name, func_type))) {
aot_set_last_error("add LLVM intrinsic function failed.");
return NULL;
}
}
}
/* Call the LLVM intrinsic function */
if (!(ret = LLVMBuildCall(comp_ctx->builder, func, param_values,
(uint32)param_count, "call"))) {
aot_set_last_error("llvm build call failed.");
aot_set_last_error("llvm build intrinsic call failed.");
return NULL;
}
@ -1936,6 +2089,7 @@ __call_llvm_intrinsic(const AOTCompContext *comp_ctx,
LLVMValueRef
aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
const AOTFuncContext *func_ctx,
const char *name,
LLVMTypeRef ret_type,
LLVMTypeRef *param_types,
@ -1961,7 +2115,7 @@ aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
param_values[i++] = va_arg(argptr, LLVMValueRef);
va_end(argptr);
ret = __call_llvm_intrinsic(comp_ctx, name, ret_type, param_types,
ret = __call_llvm_intrinsic(comp_ctx, func_ctx, name, ret_type, param_types,
param_count, param_values);
wasm_runtime_free(param_values);
@ -1971,6 +2125,7 @@ aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
LLVMValueRef
aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx,
const AOTFuncContext *func_ctx,
const char *name,
LLVMTypeRef ret_type,
LLVMTypeRef *param_types,
@ -1993,10 +2148,46 @@ aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx,
while (i < param_count)
param_values[i++] = va_arg(param_value_list, LLVMValueRef);
ret = __call_llvm_intrinsic(comp_ctx, name, ret_type, param_types,
ret = __call_llvm_intrinsic(comp_ctx, func_ctx, name, ret_type, param_types,
param_count, param_values);
wasm_runtime_free(param_values);
return ret;
}
LLVMValueRef
aot_get_func_from_table(const AOTCompContext *comp_ctx, LLVMValueRef base,
LLVMTypeRef func_type, int32 index)
{
LLVMValueRef func;
LLVMValueRef func_addr;
if (!(func_addr = I32_CONST(index))) {
aot_set_last_error("construct function index failed.");
goto fail;
}
if (!(func_addr = LLVMBuildInBoundsGEP(comp_ctx->builder, base, &func_addr,
1, "func_addr"))) {
aot_set_last_error("get function addr by index failed.");
goto fail;
}
func = LLVMBuildLoad(comp_ctx->builder, func_addr, "func_tmp");
if (func == NULL) {
aot_set_last_error("get function pointer failed.");
goto fail;
}
if (!(func = LLVMBuildBitCast(comp_ctx->builder, func, func_type,
"func"))) {
aot_set_last_error("cast function fialed.");
goto fail;
}
return func;
fail:
return NULL;
}

View File

@ -116,6 +116,7 @@ typedef struct AOTMemInfo {
typedef struct AOTFuncContext {
AOTFunc *aot_func;
LLVMValueRef func;
LLVMTypeRef func_type;
AOTBlockStack block_stack;
LLVMValueRef exec_env;
@ -124,6 +125,7 @@ typedef struct AOTFuncContext {
LLVMValueRef native_stack_bound;
LLVMValueRef aux_stack_bound;
LLVMValueRef aux_stack_bottom;
LLVMValueRef native_symbol;
LLVMValueRef last_alloca;
LLVMValueRef func_ptrs;
@ -221,10 +223,17 @@ typedef struct AOTCompContext {
char target_arch[16];
unsigned pointer_size;
/* Hardware intrinsic compability flags */
uint64 flags[8];
/* LLVM execution engine required by JIT */
LLVMExecutionEngineRef exec_engine;
bool is_jit_mode;
/* AOT indirect mode flag & symbol list */
bool is_indirect_mode;
bh_list native_symbols;
/* Bulk memory feature */
bool enable_bulk_memory;
@ -249,6 +258,9 @@ typedef struct AOTCompContext {
/* Reference Types */
bool enable_ref_types;
/* Disable LLVM built-in intrinsics */
bool disable_llvm_intrinsics;
/* Whether optimize the JITed code */
bool optimize;
@ -283,10 +295,12 @@ enum {
typedef struct AOTCompOption{
bool is_jit_mode;
bool is_indirect_mode;
char *target_arch;
char *target_abi;
char *target_cpu;
char *cpu_features;
bool is_sgx_platform;
bool enable_bulk_memory;
bool enable_thread_mgr;
bool enable_tail_call;
@ -294,7 +308,7 @@ typedef struct AOTCompOption{
bool enable_ref_types;
bool enable_aux_stack_check;
bool enable_aux_stack_frame;
bool is_sgx_platform;
bool disable_llvm_intrinsics;
uint32 opt_level;
uint32 size_level;
uint32 output_format;
@ -308,6 +322,9 @@ aot_create_comp_context(AOTCompData *comp_data,
void
aot_destroy_comp_context(AOTCompContext *comp_ctx);
int32
aot_get_native_symbol_index(AOTCompContext *comp_ctx, const char *symbol);
bool
aot_compile_wasm(AOTCompContext *comp_ctx);
@ -361,6 +378,7 @@ aot_build_zero_function_ret(AOTCompContext *comp_ctx,
LLVMValueRef
aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
const AOTFuncContext *func_ctx,
const char *name,
LLVMTypeRef ret_type,
LLVMTypeRef *param_types,
@ -369,12 +387,19 @@ aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
LLVMValueRef
aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx,
const AOTFuncContext *func_ctx,
const char *name,
LLVMTypeRef ret_type,
LLVMTypeRef *param_types,
int param_count,
va_list param_value_list);
LLVMValueRef
aot_get_func_from_table(const AOTCompContext *comp_ctx,
LLVMValueRef base,
LLVMTypeRef func_type,
int32 index);
bool
aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);

View File

@ -138,7 +138,7 @@ aot_compile_simd_swizzle_x86(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
param_types[0] = V128_i8x16_TYPE;
param_types[1] = V128_i8x16_TYPE;
if (!(result = aot_call_llvm_intrinsic(
comp_ctx, "llvm.x86.ssse3.pshuf.b.128", V128_i8x16_TYPE,
comp_ctx, func_ctx, "llvm.x86.ssse3.pshuf.b.128", V128_i8x16_TYPE,
param_types, 2, vector, mask))) {
HANDLE_FAILURE("LLVMBuildCall");
goto fail;

View File

@ -69,7 +69,7 @@ simd_build_bitmask(const AOTCompContext *comp_ctx,
}
param_types[0] = vector_ext_type;
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, I32_TYPE,
if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, I32_TYPE,
param_types, 1, result))) {
HANDLE_FAILURE("LLVMBuildCall");
goto fail;

View File

@ -41,7 +41,7 @@ simd_any_true(AOTCompContext *comp_ctx,
goto fail;
}
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, element_type,
if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, element_type,
&vector_type, 1, non_zero))) {
HANDLE_FAILURE("LLVMBuildCall");
goto fail;
@ -128,7 +128,7 @@ simd_all_true(AOTCompContext *comp_ctx,
goto fail;
}
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, element_type,
if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, element_type,
&vector_type, 1, is_zero))) {
HANDLE_FAILURE("LLVMBuildCall");
goto fail;

View File

@ -38,7 +38,7 @@ simd_integer_narrow(AOTCompContext *comp_ctx,
}
if (!(result =
aot_call_llvm_intrinsic(comp_ctx, instrinsic, out_vector_type,
aot_call_llvm_intrinsic(comp_ctx, func_ctx, instrinsic, out_vector_type,
param_types, 2, vector1, vector2))) {
HANDLE_FAILURE("LLVMBuildCall");
goto fail;

View File

@ -191,7 +191,7 @@ simd_v128_float_intrinsic(AOTCompContext *comp_ctx,
goto fail;
}
if (!(result = aot_call_llvm_intrinsic(comp_ctx, intrinsic, vector_type,
if (!(result = aot_call_llvm_intrinsic(comp_ctx, func_ctx, intrinsic, vector_type,
param_types, 1, number))) {
HANDLE_FAILURE("LLVMBuildCall");
goto fail;

View File

@ -32,7 +32,7 @@ simd_v128_integer_arith(AOTCompContext *comp_ctx,
param_types[1] = vector_type;
if (!(result = aot_call_llvm_intrinsic(
comp_ctx, is_signed ? intrinsics_s_u[0] : intrinsics_s_u[1],
comp_ctx, func_ctx, is_signed ? intrinsics_s_u[0] : intrinsics_s_u[1],
vector_type, param_types, 2, lhs, rhs))) {
HANDLE_FAILURE("LLVMBuildCall");
goto fail;

View File

@ -35,10 +35,12 @@ enum {
typedef struct AOTCompOption{
bool is_jit_mode;
bool is_indirect_mode;
char *target_arch;
char *target_abi;
char *target_cpu;
char *cpu_features;
bool is_sgx_platform;
bool enable_bulk_memory;
bool enable_thread_mgr;
bool enable_tail_call;
@ -46,7 +48,7 @@ typedef struct AOTCompOption{
bool enable_ref_types;
bool enable_aux_stack_check;
bool enable_aux_stack_frame;
bool is_sgx_platform;
bool disable_llvm_intrinsics;
uint32_t opt_level;
uint32_t size_level;
uint32_t output_format;

View File

@ -132,76 +132,110 @@ static union {
/* Get two 32 bit ints from a double. */
#define EXTRACT_WORDS_L(ix0,ix1,d) \
do { \
ieee_double_shape_type_little ew_u; \
ew_u.value = (d); \
(ix0) = ew_u.parts.msw; \
(ix1) = ew_u.parts.lsw; \
#define EXTRACT_WORDS_L(ix0,ix1,d) \
do { \
ieee_double_shape_type_little ew_u; \
ew_u.value = (d); \
(ix0) = ew_u.parts.msw; \
(ix1) = ew_u.parts.lsw; \
} while (0)
/* Set a double from two 32 bit ints. */
#define INSERT_WORDS_L(d,ix0,ix1) \
do { \
ieee_double_shape_type_little iw_u; \
iw_u.parts.msw = (ix0); \
iw_u.parts.lsw = (ix1); \
(d) = iw_u.value; \
#define INSERT_WORDS_L(d,ix0,ix1) \
do { \
ieee_double_shape_type_little iw_u; \
iw_u.parts.msw = (ix0); \
iw_u.parts.lsw = (ix1); \
(d) = iw_u.value; \
} while (0)
/* Get two 32 bit ints from a double. */
#define EXTRACT_WORDS_B(ix0,ix1,d) \
do { \
ieee_double_shape_type_big ew_u; \
ew_u.value = (d); \
(ix0) = ew_u.parts.msw; \
(ix1) = ew_u.parts.lsw; \
#define EXTRACT_WORDS_B(ix0,ix1,d) \
do { \
ieee_double_shape_type_big ew_u; \
ew_u.value = (d); \
(ix0) = ew_u.parts.msw; \
(ix1) = ew_u.parts.lsw; \
} while (0)
/* Set a double from two 32 bit ints. */
#define INSERT_WORDS_B(d,ix0,ix1) \
do { \
ieee_double_shape_type_big iw_u; \
iw_u.parts.msw = (ix0); \
iw_u.parts.lsw = (ix1); \
(d) = iw_u.value; \
#define INSERT_WORDS_B(d,ix0,ix1) \
do { \
ieee_double_shape_type_big iw_u; \
iw_u.parts.msw = (ix0); \
iw_u.parts.lsw = (ix1); \
(d) = iw_u.value; \
} while (0)
/* Get the more significant 32 bit int from a double. */
#define GET_HIGH_WORD_L(i,d) \
do { \
ieee_double_shape_type_little gh_u; \
gh_u.value = (d); \
(i) = gh_u.parts.msw; \
#define GET_HIGH_WORD_L(i,d) \
do { \
ieee_double_shape_type_little gh_u; \
gh_u.value = (d); \
(i) = gh_u.parts.msw; \
} while (0)
/* Get the more significant 32 bit int from a double. */
#define GET_HIGH_WORD_B(i,d) \
do { \
ieee_double_shape_type_big gh_u; \
gh_u.value = (d); \
(i) = gh_u.parts.msw; \
#define GET_HIGH_WORD_B(i,d) \
do { \
ieee_double_shape_type_big gh_u; \
gh_u.value = (d); \
(i) = gh_u.parts.msw; \
} while (0)
/* Set the more significant 32 bits of a double from an int. */
#define SET_HIGH_WORD_L(d,v) \
do { \
ieee_double_shape_type_little sh_u; \
sh_u.value = (d); \
sh_u.parts.msw = (v); \
(d) = sh_u.value; \
#define SET_HIGH_WORD_L(d,v) \
do { \
ieee_double_shape_type_little sh_u; \
sh_u.value = (d); \
sh_u.parts.msw = (v); \
(d) = sh_u.value; \
} while (0)
/* Set the more significant 32 bits of a double from an int. */
#define SET_HIGH_WORD_B(d,v) \
do { \
ieee_double_shape_type_big sh_u; \
sh_u.value = (d); \
sh_u.parts.msw = (v); \
(d) = sh_u.value; \
#define SET_HIGH_WORD_B(d,v) \
do { \
ieee_double_shape_type_big sh_u; \
sh_u.value = (d); \
sh_u.parts.msw = (v); \
(d) = sh_u.value; \
} while (0)
/* Set the less significant 32 bits of a double from an int. */
#define SET_LOW_WORD_L(d,v) \
do { \
ieee_double_shape_type_little sh_u; \
sh_u.value = (d); \
sh_u.parts.lsw = (v); \
(d) = sh_u.value; \
} while (0)
/* Set the more significant 32 bits of a double from an int. */
#define SET_LOW_WORD_B(d,v) \
do { \
ieee_double_shape_type_big sh_u; \
sh_u.value = (d); \
sh_u.parts.lsw = (v); \
(d) = sh_u.value; \
} while (0)
/* Get the less significant 32 bit int from a double. */
#define GET_LOW_WORD_L(i,d) \
do { \
ieee_double_shape_type_little gl_u; \
gl_u.value = (d); \
(i) = gl_u.parts.lsw; \
} while (0)
/* Get the less significant 32 bit int from a double. */
#define GET_LOW_WORD_B(i,d) \
do { \
ieee_double_shape_type_big gl_u; \
gl_u.value = (d); \
(i) = gl_u.parts.lsw; \
} while (0)
/*
@ -262,6 +296,22 @@ typedef union
SET_HIGH_WORD_B(d,v); \
} while (0)
#define GET_LOW_WORD(d,v) \
do { \
if (is_little_endian()) \
GET_LOW_WORD_L(d,v); \
else \
GET_LOW_WORD_B(d,v); \
} while (0)
#define SET_LOW_WORD(d,v) \
do { \
if (is_little_endian()) \
SET_LOW_WORD_L(d,v); \
else \
SET_LOW_WORD_B(d,v); \
} while (0)
#define __HI(x) (is_little_endian() ? __HIL(x) : __HIB(x))
#define __LO(x) (is_little_endian() ? __LOL(x) : __LOB(x))
@ -314,12 +364,219 @@ TWO52[2]={
-4.50359962737049600000e+15, /* 0xC3300000, 0x00000000 */
};
#ifdef __STDC__
static const double
#else
static double
#endif
atanhi[] = {
4.63647609000806093515e-01, /* atan(0.5)hi 0x3FDDAC67, 0x0561BB4F */
7.85398163397448278999e-01, /* atan(1.0)hi 0x3FE921FB, 0x54442D18 */
9.82793723247329054082e-01, /* atan(1.5)hi 0x3FEF730B, 0xD281F69B */
1.57079632679489655800e+00, /* atan(inf)hi 0x3FF921FB, 0x54442D18 */
};
#ifdef __STDC__
static const double
#else
static double
#endif
atanlo[] = {
2.26987774529616870924e-17, /* atan(0.5)lo 0x3C7A2B7F, 0x222F65E2 */
3.06161699786838301793e-17, /* atan(1.0)lo 0x3C81A626, 0x33145C07 */
1.39033110312309984516e-17, /* atan(1.5)lo 0x3C700788, 0x7AF0CBBD */
6.12323399573676603587e-17, /* atan(inf)lo 0x3C91A626, 0x33145C07 */
};
#ifdef __STDC__
static const double
#else
static double
#endif
aT[] = {
3.33333333333329318027e-01, /* 0x3FD55555, 0x5555550D */
-1.99999999998764832476e-01, /* 0xBFC99999, 0x9998EBC4 */
1.42857142725034663711e-01, /* 0x3FC24924, 0x920083FF */
-1.11111104054623557880e-01, /* 0xBFBC71C6, 0xFE231671 */
9.09088713343650656196e-02, /* 0x3FB745CD, 0xC54C206E */
-7.69187620504482999495e-02, /* 0xBFB3B0F2, 0xAF749A6D */
6.66107313738753120669e-02, /* 0x3FB10D66, 0xA0D03D51 */
-5.83357013379057348645e-02, /* 0xBFADDE2D, 0x52DEFD9A */
4.97687799461593236017e-02, /* 0x3FA97B4B, 0x24760DEB */
-3.65315727442169155270e-02, /* 0xBFA2B444, 0x2C6A6C2F */
1.62858201153657823623e-02, /* 0x3F90AD3A, 0xE322DA11 */
};
#ifdef __STDC__
static const double
#else
static double
#endif
zero = 0.0,
pi_o_4 = 7.8539816339744827900E-01, /* 0x3FE921FB, 0x54442D18 */
pi_o_2 = 1.5707963267948965580E+00, /* 0x3FF921FB, 0x54442D18 */
pi = 3.1415926535897931160E+00, /* 0x400921FB, 0x54442D18 */
pi_lo = 1.2246467991473531772E-16; /* 0x3CA1A626, 0x33145C07 */
#ifdef __STDC__
static const double
#else
static double
#endif
bp[] = {1.0, 1.5,},
dp_h[] = { 0.0, 5.84962487220764160156e-01,}, /* 0x3FE2B803, 0x40000000 */
dp_l[] = { 0.0, 1.35003920212974897128e-08,}, /* 0x3E4CFDEB, 0x43CFD006 */
two = 2.0,
two53 = 9007199254740992.0, /* 0x43400000, 0x00000000 */
two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
L1 = 5.99999999999994648725e-01, /* 0x3FE33333, 0x33333303 */
L2 = 4.28571428578550184252e-01, /* 0x3FDB6DB6, 0xDB6FABFF */
L3 = 3.33333329818377432918e-01, /* 0x3FD55555, 0x518F264D */
L4 = 2.72728123808534006489e-01, /* 0x3FD17460, 0xA91D4101 */
L5 = 2.30660745775561754067e-01, /* 0x3FCD864A, 0x93C9DB65 */
L6 = 2.06975017800338417784e-01, /* 0x3FCA7E28, 0x4A454EEF */
P1 = 1.66666666666666019037e-01, /* 0x3FC55555, 0x5555553E */
P2 = -2.77777777770155933842e-03, /* 0xBF66C16C, 0x16BEBD93 */
P3 = 6.61375632143793436117e-05, /* 0x3F11566A, 0xAF25DE2C */
P4 = -1.65339022054652515390e-06, /* 0xBEBBBD41, 0xC5D26BF1 */
P5 = 4.13813679705723846039e-08, /* 0x3E663769, 0x72BEA4D0 */
lg2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
lg2_h = 6.93147182464599609375e-01, /* 0x3FE62E43, 0x00000000 */
lg2_l = -1.90465429995776804525e-09, /* 0xBE205C61, 0x0CA86C39 */
ovt = 8.0085662595372944372e-0017, /* -(1024-log2(ovfl+.5ulp)) */
cp = 9.61796693925975554329e-01, /* 0x3FEEC709, 0xDC3A03FD =2/(3ln2) */
cp_h = 9.61796700954437255859e-01, /* 0x3FEEC709, 0xE0000000 =(float)cp */
cp_l = -7.02846165095275826516e-09, /* 0xBE3E2FE0, 0x145B01F5 =tail of cp_h*/
ivln2 = 1.44269504088896338700e+00, /* 0x3FF71547, 0x652B82FE =1/ln2 */
ivln2_h = 1.44269502162933349609e+00, /* 0x3FF71547, 0x60000000 =24b 1/ln2*/
ivln2_l = 1.92596299112661746887e-08; /* 0x3E54AE0B, 0xF85DDF44 =1/ln2 tail*/
static double freebsd_sqrt(double x);
static double freebsd_floor(double x);
static double freebsd_ceil(double x);
static double freebsd_fabs(double x);
static double freebsd_rint(double x);
static int freebsd_isnan(double x);
static double freebsd_atan(double x);
static double freebsd_atan2(double y, double x);
static double freebsd_atan(double x)
{
double w,s1,s2,z;
int32_t ix,hx,id;
GET_HIGH_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix>=0x44100000) { /* if |x| >= 2^66 */
u_int32_t low;
GET_LOW_WORD(low,x);
if(ix>0x7ff00000||
(ix==0x7ff00000&&(low!=0)))
return x+x; /* NaN */
if(hx>0) return atanhi[3]+*(volatile double *)&atanlo[3];
else return -atanhi[3]-*(volatile double *)&atanlo[3];
} if (ix < 0x3fdc0000) { /* |x| < 0.4375 */
if (ix < 0x3e400000) { /* |x| < 2^-27 */
if(huge+x>one) return x; /* raise inexact */
}
id = -1;
} else {
x = freebsd_fabs(x);
if (ix < 0x3ff30000) { /* |x| < 1.1875 */
if (ix < 0x3fe60000) { /* 7/16 <=|x|<11/16 */
id = 0; x = (2.0*x-one)/(2.0+x);
} else { /* 11/16<=|x|< 19/16 */
id = 1; x = (x-one)/(x+one);
}
} else {
if (ix < 0x40038000) { /* |x| < 2.4375 */
id = 2; x = (x-1.5)/(one+1.5*x);
} else { /* 2.4375 <= |x| < 2^66 */
id = 3; x = -1.0/x;
}
}}
/* end of argument reduction */
z = x*x;
w = z*z;
/* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
if (id<0) return x - x*(s1+s2);
else {
z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
return (hx<0)? -z:z;
}
}
static double freebsd_atan2(double y, double x)
{
double z;
int32_t k,m,hx,hy,ix,iy;
u_int32_t lx,ly;
EXTRACT_WORDS(hx,lx,x);
ix = hx&0x7fffffff;
EXTRACT_WORDS(hy,ly,y);
iy = hy&0x7fffffff;
if(((ix|((lx|-lx)>>31))>0x7ff00000)||
((iy|((ly|-ly)>>31))>0x7ff00000)) /* x or y is NaN */
return x+y;
if(hx==0x3ff00000&&lx==0) return freebsd_atan(y); /* x=1.0 */
m = ((hy>>31)&1)|((hx>>30)&2); /* 2*sign(x)+sign(y) */
/* when y = 0 */
if((iy|ly)==0) {
switch(m) {
case 0:
case 1: return y; /* atan(+-0,+anything)=+-0 */
case 2: return pi+tiny;/* atan(+0,-anything) = pi */
case 3: return -pi-tiny;/* atan(-0,-anything) =-pi */
}
}
/* when x = 0 */
if((ix|lx)==0) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
/* when x is INF */
if(ix==0x7ff00000) {
if(iy==0x7ff00000) {
switch(m) {
case 0: return pi_o_4+tiny;/* atan(+INF,+INF) */
case 1: return -pi_o_4-tiny;/* atan(-INF,+INF) */
case 2: return 3.0*pi_o_4+tiny;/*atan(+INF,-INF)*/
case 3: return -3.0*pi_o_4-tiny;/*atan(-INF,-INF)*/
}
} else {
switch(m) {
case 0: return zero ; /* atan(+...,+INF) */
case 1: return -zero ; /* atan(-...,+INF) */
case 2: return pi+tiny ; /* atan(+...,-INF) */
case 3: return -pi-tiny ; /* atan(-...,-INF) */
}
}
}
/* when y is INF */
if(iy==0x7ff00000) return (hy<0)? -pi_o_2-tiny: pi_o_2+tiny;
/* compute y/x */
k = (iy-ix)>>20;
if(k > 60) { /* |y/x| > 2**60 */
z=pi_o_2+0.5*pi_lo;
m&=1;
}
else if(hx<0&&k<-60) z=0.0; /* 0 > |y|/x > -2**-60 */
else z=freebsd_atan(fabs(y/x)); /* safe to do y/x */
switch (m) {
case 0: return z ; /* atan(+,+) */
case 1: return -z ; /* atan(-,+) */
case 2: return pi-(z-pi_lo);/* atan(+,-) */
default: /* case 3 */
return (z-pi_lo)-pi;/* atan(-,-) */
}
}
static double freebsd_sqrt(double x) /* wrapper sqrt */
{
@ -777,6 +1034,271 @@ freebsd_fmaxf(float x, float y)
return (x > y ? x : y);
}
static double
freebsd_copysign(double x, double y)
{
u_int32_t hx,hy;
GET_HIGH_WORD(hx,x);
GET_HIGH_WORD(hy,y);
SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000));
return x;
}
static double
freebsd_scalbn(double x, int n)
{
int32_t k,hx,lx;
EXTRACT_WORDS(hx,lx,x);
k = (hx&0x7ff00000)>>20; /* extract exponent */
if (k==0) { /* 0 or subnormal x */
if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
x *= two54;
GET_HIGH_WORD(hx,x);
k = ((hx&0x7ff00000)>>20) - 54;
if (n< -50000) return tiny*x; /*underflow*/
}
if (k==0x7ff) return x+x; /* NaN or Inf */
k = k+n;
if (k > 0x7fe) return huge*freebsd_copysign(huge,x); /* overflow */
if (k > 0) /* normal result */
{SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
if (k <= -54) {
if (n > 50000) /* in case integer overflow in n+k */
return huge*freebsd_copysign(huge,x); /*overflow*/
else return tiny*freebsd_copysign(tiny,x); /*underflow*/
}
k += 54; /* subnormal result */
SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
return x*twom54;
}
static double
freebsd_pow(double x, double y)
{
double z,ax,z_h,z_l,p_h,p_l;
double y1,t1,t2,r,s,t,u,v,w;
int32_t i,j,k,yisint,n;
int32_t hx,hy,ix,iy;
u_int32_t lx,ly;
EXTRACT_WORDS(hx,lx,x);
EXTRACT_WORDS(hy,ly,y);
ix = hx&0x7fffffff; iy = hy&0x7fffffff;
/* y==zero: x**0 = 1 */
if((iy|ly)==0) return one;
/* x==1: 1**y = 1, even if y is NaN */
if (hx==0x3ff00000 && lx == 0) return one;
/* y!=zero: result is NaN if either arg is NaN */
if(ix > 0x7ff00000 || ((ix==0x7ff00000)&&(lx!=0)) ||
iy > 0x7ff00000 || ((iy==0x7ff00000)&&(ly!=0)))
return (x+0.0)+(y+0.0);
/* determine if y is an odd int when x < 0
* yisint = 0 ... y is not an integer
* yisint = 1 ... y is an odd int
* yisint = 2 ... y is an even int
*/
yisint = 0;
if(hx<0) {
if(iy>=0x43400000) yisint = 2; /* even integer y */
else if(iy>=0x3ff00000) {
k = (iy>>20)-0x3ff; /* exponent */
if(k>20) {
j = ly>>(52-k);
if((j<<(52-k))==ly) yisint = 2-(j&1);
} else if(ly==0) {
j = iy>>(20-k);
if((j<<(20-k))==iy) yisint = 2-(j&1);
}
}
}
/* special value of y */
if(ly==0) {
if (iy==0x7ff00000) { /* y is +-inf */
if(((ix-0x3ff00000)|lx)==0)
return one; /* (-1)**+-inf is NaN */
else if (ix >= 0x3ff00000)/* (|x|>1)**+-inf = inf,0 */
return (hy>=0)? y: zero;
else /* (|x|<1)**-,+inf = inf,0 */
return (hy<0)?-y: zero;
}
if(iy==0x3ff00000) { /* y is +-1 */
if(hy<0) return one/x; else return x;
}
if(hy==0x40000000) return x*x; /* y is 2 */
if(hy==0x40080000) return x*x*x; /* y is 3 */
if(hy==0x40100000) { /* y is 4 */
u = x*x;
return u*u;
}
if(hy==0x3fe00000) { /* y is 0.5 */
if(hx>=0) /* x >= +0 */
return sqrt(x);
}
}
ax = fabs(x);
/* special value of x */
if(lx==0) {
if(ix==0x7ff00000||ix==0||ix==0x3ff00000){
z = ax; /*x is +-0,+-inf,+-1*/
if(hy<0) z = one/z; /* z = (1/|x|) */
if(hx<0) {
if(((ix-0x3ff00000)|yisint)==0) {
z = (z-z)/(z-z); /* (-1)**non-int is NaN */
} else if(yisint==1)
z = -z; /* (x<0)**odd = -(|x|**odd) */
}
return z;
}
}
/* CYGNUS LOCAL + fdlibm-5.3 fix: This used to be
n = (hx>>31)+1;
but ANSI C says a right shift of a signed negative quantity is
implementation defined. */
n = ((u_int32_t)hx>>31)-1;
/* (x<0)**(non-int) is NaN */
if((n|yisint)==0) return (x-x)/(x-x);
s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
if((n|(yisint-1))==0) s = -one;/* (-ve)**(odd int) */
/* |y| is huge */
if(iy>0x41e00000) { /* if |y| > 2**31 */
if(iy>0x43f00000){ /* if |y| > 2**64, must o/uflow */
if(ix<=0x3fefffff) return (hy<0)? huge*huge:tiny*tiny;
if(ix>=0x3ff00000) return (hy>0)? huge*huge:tiny*tiny;
}
/* over/underflow if x is not close to one */
if(ix<0x3fefffff) return (hy<0)? s*huge*huge:s*tiny*tiny;
if(ix>0x3ff00000) return (hy>0)? s*huge*huge:s*tiny*tiny;
/* now |1-x| is tiny <= 2**-20, suffice to compute
log(x) by x-x^2/2+x^3/3-x^4/4 */
t = ax-one; /* t has 20 trailing zeros */
w = (t*t)*(0.5-t*(0.3333333333333333333333-t*0.25));
u = ivln2_h*t; /* ivln2_h has 21 sig. bits */
v = t*ivln2_l-w*ivln2;
t1 = u+v;
SET_LOW_WORD(t1,0);
t2 = v-(t1-u);
} else {
double ss,s2,s_h,s_l,t_h,t_l;
n = 0;
/* take care subnormal number */
if(ix<0x00100000)
{ax *= two53; n -= 53; GET_HIGH_WORD(ix,ax); }
n += ((ix)>>20)-0x3ff;
j = ix&0x000fffff;
/* determine interval */
ix = j|0x3ff00000; /* normalize ix */
if(j<=0x3988E) k=0; /* |x|<sqrt(3/2) */
else if(j<0xBB67A) k=1; /* |x|<sqrt(3) */
else {k=0;n+=1;ix -= 0x00100000;}
SET_HIGH_WORD(ax,ix);
/* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
v = one/(ax+bp[k]);
ss = u*v;
s_h = ss;
SET_LOW_WORD(s_h,0);
/* t_h=ax+bp[k] High */
t_h = zero;
SET_HIGH_WORD(t_h,((ix>>1)|0x20000000)+0x00080000+(k<<18));
t_l = ax - (t_h-bp[k]);
s_l = v*((u-s_h*t_h)-s_h*t_l);
/* compute log(ax) */
s2 = ss*ss;
r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
r += s_l*(s_h+ss);
s2 = s_h*s_h;
t_h = 3.0+s2+r;
SET_LOW_WORD(t_h,0);
t_l = r-((t_h-3.0)-s2);
/* u+v = ss*(1+...) */
u = s_h*t_h;
v = s_l*t_h+t_l*ss;
/* 2/(3log2)*(ss+...) */
p_h = u+v;
SET_LOW_WORD(p_h,0);
p_l = v-(p_h-u);
z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
z_l = cp_l*p_h+p_l*cp+dp_l[k];
/* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */
t = (double)n;
t1 = (((z_h+z_l)+dp_h[k])+t);
SET_LOW_WORD(t1,0);
t2 = z_l-(((t1-t)-dp_h[k])-z_h);
}
/* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
y1 = y;
SET_LOW_WORD(y1,0);
p_l = (y-y1)*t1+y*t2;
p_h = y1*t1;
z = p_l+p_h;
EXTRACT_WORDS(j,i,z);
if (j>=0x40900000) { /* z >= 1024 */
if(((j-0x40900000)|i)!=0) /* if z > 1024 */
return s*huge*huge; /* overflow */
else {
if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */
}
} else if((j&0x7fffffff)>=0x4090cc00 ) { /* z <= -1075 */
if(((j-0xc090cc00)|i)!=0) /* z < -1075 */
return s*tiny*tiny; /* underflow */
else {
if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */
}
}
/*
* compute 2**(p_h+p_l)
*/
i = j&0x7fffffff;
k = (i>>20)-0x3ff;
n = 0;
if(i>0x3fe00000) { /* if |z| > 0.5, set n = [z+0.5] */
n = j+(0x00100000>>(k+1));
k = ((n&0x7fffffff)>>20)-0x3ff; /* new k for n */
t = zero;
SET_HIGH_WORD(t,n&~(0x000fffff>>k));
n = ((n&0x000fffff)|0x00100000)>>(20-k);
if(j<0) n = -n;
p_h -= t;
}
t = p_l+p_h;
SET_LOW_WORD(t,0);
u = t*lg2_h;
v = (p_l-(t-p_h))*lg2+t*lg2_l;
z = u+v;
w = v-(z-u);
t = z*z;
t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
r = (z*t1)/(t1-two)-(w+z*w);
z = one-(r-z);
GET_HIGH_WORD(j,z);
j += (n<<20);
if((j>>20)<=0) z = freebsd_scalbn(z,n); /* subnormal output */
else SET_HIGH_WORD(z,j);
return s*z;
}
double atan(double x)
{
return freebsd_atan(x);
}
double atan2(double y, double x)
{
return freebsd_atan2(y, x);
}
double sqrt(double x)
{
return freebsd_sqrt(x);
@ -863,3 +1385,14 @@ fmaxf(float x, float y)
return freebsd_fmaxf(x, y);
}
double
pow(double x, double y)
{
return freebsd_pow(x, y);
}
double
scalbn(double x, int n)
{
return freebsd_scalbn(x, n);
}

View File

@ -305,7 +305,7 @@ uint8 *os_thread_get_stack_boundary()
addr += guard_size;
}
(void)stack_size;
#elif defined(__APPLE__)
#elif defined(__APPLE__) || defined(__NuttX__)
if ((addr = (uint8*)pthread_get_stackaddr_np(self))) {
stack_size = pthread_get_stacksize_np(self);
if (stack_size > max_stack_size)

View File

@ -67,6 +67,8 @@ size_t strspn(const char *s, const char *accept);
size_t strcspn(const char *s, const char *reject);
/* math functions which are not provided by os */
double atan(double x);
double atan2(double y, double x);
double sqrt(double x);
double floor(double x);
double ceil(double x);
@ -83,6 +85,8 @@ float rintf(float x);
float truncf(float x);
int signbit(double x);
int isnan(double x);
double pow(double x, double y);
double scalbn(double x, int n);
unsigned long long int strtoull(const char *nptr, char **endptr, int base);
double strtod(const char *nptr, char **endptr);

View File

@ -202,6 +202,11 @@ os_dcache_flush()
key = irq_lock();
SCB_CleanDCache();
irq_unlock(key);
#elif defined(CONFIG_SOC_CVF_EM7D) && defined(CONFIG_ARC_MPU) \
&& defined (CONFIG_CACHE_FLUSHING)
__asm__ __volatile__("sync");
z_arc_v2_aux_reg_write(_ARC_V2_DC_FLSH, BIT(0));
__asm__ __volatile__("sync");
#endif
}

View File

@ -35,11 +35,11 @@ endif
WAMR_BUILD_PLATFORM := nuttx
ifeq (${WAMR_BUILD_TARGET}, X86_32)
ifeq ($(WAMR_BUILD_TARGET), X86_32)
CFLAGS += -DBUILD_TARGET_X86_32
INVOKE_NATIVE := invokeNative_ia32.s
AOT_RELOC := aot_reloc_x86_32.c
else ifeq (${WAMR_BUILD_TARGET}, X86_64)
else ifeq ($(WAMR_BUILD_TARGET), X86_64)
CFLAGS += -DBUILD_TARGET_X86_64
INVOKE_NATIVE := invokeNative_em64.s
AOT_RELOC := aot_reloc_x86_64.c
@ -96,17 +96,18 @@ else
$(error Build target is unsupported)
endif
ifeq (${CONFIG_INTERPRETERS_WAMR_LOG},y)
ifeq ($(CONFIG_INTERPRETERS_WAMR_LOG),y)
CFLAGS += -DWASM_ENABLE_LOG=1
else
CFLAGS += -DWASM_ENABLE_LOG=0
endif
ifeq (${CONFIG_INTERPRETERS_WAMR_AOT},y)
CFLAGS += -I${IWASM_ROOT}/aot
ifeq ($(CONFIG_INTERPRETERS_WAMR_AOT),y)
CFLAGS += -I$(IWASM_ROOT)/aot
CFLAGS += -DWASM_ENABLE_AOT=1
CSRCS += aot_loader.c \
${AOT_RELOC} \
$(AOT_RELOC) \
aot_intrinsic.c \
aot_runtime.c
else
CFLAGS += -DWASM_ENABLE_AOT=0
@ -115,7 +116,7 @@ endif
CFLAGS += -DWASM_ENABLE_INTERP=1
CSRCS += wasm_runtime.c
ifeq (${CONFIG_INTERPRETERS_WAMR_FAST},y)
ifeq ($(CONFIG_INTERPRETERS_WAMR_FAST),y)
CFLAGS += -DWASM_ENABLE_FAST_INTERP=1
CSRCS += wasm_interp_fast.c
else
@ -137,7 +138,7 @@ endif
ifeq ($(CONFIG_INTERPRETERS_WAMR_THREAD_MGR),y)
CFLAGS += -DWASM_ENABLE_THREAD_MGR=1
CSRCS += thread_manager.c
VPATH += ${IWASM_ROOT}/libraries/thread-mgr
VPATH += $(IWASM_ROOT)/libraries/thread-mgr
else
CFLAGS += -DWASM_ENABLE_THREAD_MGR=0
endif
@ -191,9 +192,8 @@ CFLAGS += -I${CORE_ROOT} \
-I${SHARED_ROOT}/mem-alloc \
-I${SHARED_ROOT}/platform/nuttx
ifeq (${WAMR_BUILD_INTERP}, 1)
CFLAGS += -I${IWASM_ROOT}/interpreter
ifeq ($(WAMR_BUILD_INTERP), 1)
CFLAGS += -I$(IWASM_ROOT)/interpreter
endif
CSRCS += nuttx_platform.c \
@ -220,19 +220,19 @@ CSRCS += nuttx_platform.c \
wasm_memory.c \
wasm_c_api.c
ASRCS += ${INVOKE_NATIVE}
ASRCS += $(INVOKE_NATIVE)
VPATH += ${SHARED_ROOT}/platform/nuttx
VPATH += ${SHARED_ROOT}/platform/common/posix
VPATH += ${SHARED_ROOT}/mem-alloc
VPATH += ${SHARED_ROOT}/mem-alloc/ems
VPATH += ${SHARED_ROOT}/utils
VPATH += ${SHARED_ROOT}/utils/uncommon
VPATH += ${IWASM_ROOT}/common
VPATH += ${IWASM_ROOT}/interpreter
VPATH += ${IWASM_ROOT}/libraries
VPATH += ${IWASM_ROOT}/libraries/libc-builtin
VPATH += ${IWASM_ROOT}/libraries/lib-pthread
VPATH += ${IWASM_ROOT}/common/arch
VPATH += ${IWASM_ROOT}/aot
VPATH += ${IWASM_ROOT}/aot/arch
VPATH += $(SHARED_ROOT)/platform/nuttx
VPATH += $(SHARED_ROOT)/platform/common/posix
VPATH += $(SHARED_ROOT)/mem-alloc
VPATH += $(SHARED_ROOT)/mem-alloc/ems
VPATH += $(SHARED_ROOT)/utils
VPATH += $(SHARED_ROOT)/utils/uncommon
VPATH += $(IWASM_ROOT)/common
VPATH += $(IWASM_ROOT)/interpreter
VPATH += $(IWASM_ROOT)/libraries
VPATH += $(IWASM_ROOT)/libraries/libc-builtin
VPATH += $(IWASM_ROOT)/libraries/lib-pthread
VPATH += $(IWASM_ROOT)/common/arch
VPATH += $(IWASM_ROOT)/aot
VPATH += $(IWASM_ROOT)/aot/arch

View File

@ -32,7 +32,9 @@ print_help()
printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n");
printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n");
printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n"
" that runs commands in the form of `FUNC ARG...`\n");
" that runs commands in the form of \"FUNC ARG...\"\n");
printf(" --xip Enable XIP (Execution In Place) mode to run AOT file\n"
" generated with \"--enable-indirect-mode\" flag\n");
#if WASM_ENABLE_LIBC_WASI != 0
printf(" --env=<env> Pass wasi environment variables with \"key=value\"\n");
printf(" to the program, for example:\n");
@ -232,6 +234,7 @@ main(int argc, char *argv[])
int log_verbose_level = 2;
#endif
bool is_repl_mode = false;
bool is_xip_mode = false;
#if WASM_ENABLE_LIBC_WASI != 0
const char *dir_list[8] = { NULL };
uint32 dir_list_size = 0;
@ -259,6 +262,9 @@ main(int argc, char *argv[])
else if (!strcmp(argv[0], "--repl")) {
is_repl_mode = true;
}
else if (!strcmp(argv[0], "--xip")) {
is_xip_mode = true;
}
else if (!strncmp(argv[0], "--stack-size=", 13)) {
if (argv[0][13] == '\0')
return print_help();
@ -355,6 +361,24 @@ main(int argc, char *argv[])
(uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size)))
goto fail1;
if (is_xip_mode) {
uint8 *wasm_file_mapped;
int map_prot = MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC;
int map_flags = MMAP_MAP_NONE;
if (!(wasm_file_mapped = os_mmap(NULL, (uint32)wasm_file_size,
map_prot, map_flags))) {
printf("mmap memory failed\n");
wasm_runtime_free(wasm_file_buf);
goto fail1;
}
bh_memcpy_s(wasm_file_mapped, wasm_file_size,
wasm_file_buf, wasm_file_size);
wasm_runtime_free(wasm_file_buf);
wasm_file_buf = wasm_file_mapped;
}
#if WASM_ENABLE_MULTI_MODULE != 0
wasm_runtime_set_module_reader(module_reader_callback, moudle_destroyer);
#endif
@ -395,7 +419,10 @@ fail3:
fail2:
/* free the file buffer */
wasm_runtime_free(wasm_file_buf);
if (!is_xip_mode)
wasm_runtime_free(wasm_file_buf);
else
os_munmap(wasm_file_buf, wasm_file_size);
fail1:
/* destroy runtime environment */

View File

@ -10,11 +10,12 @@ QEMU_CORTEX_A53="qemu_cortex_a53"
QEMU_XTENSA_TARGET="qemu_xtensa"
QEMU_RISCV64_TARGET="qemu_riscv64"
QEMU_RISCV32_TARGET="qemu_riscv32"
QEMU_ARC_TARGET="qemu_arc"
usage ()
{
echo "USAGE:"
echo "$0 $X86_TARGET|$STM32_TARGET|$ESP32_TARGET|$QEMU_CORTEX_A53|$QEMU_XTENSA_TARGET|$QEMU_RISCV64_TARGET|$QEMU_RISCV32_TARGET"
echo "$0 $X86_TARGET|$STM32_TARGET|$ESP32_TARGET|$QEMU_CORTEX_A53|$QEMU_XTENSA_TARGET|$QEMU_RISCV64_TARGET|$QEMU_RISCV32_TARGET|$QEMU_ARC_TARGET"
echo "Example:"
echo " $0 $X86_TARGET"
echo " $0 $STM32_TARGET"
@ -88,6 +89,14 @@ case $TARGET in
-DWAMR_BUILD_AOT=0
west build -t run
;;
$QEMU_ARC_TARGET)
west build -b qemu_arc_em \
. -p always -- \
-DCONF_FILE=prj_qemu_arc.conf \
-DWAMR_BUILD_TARGET=ARC \
-DWAMR_BUILD_AOT=0
west build -t run
;;
*)
echo "unsupported target: $TARGET"
usage

View File

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

View File

@ -64,10 +64,42 @@ static void*
app_instance_main(wasm_module_inst_t module_inst)
{
const char *exception;
wasm_function_inst_t func;
wasm_exec_env_t exec_env;
unsigned argv[2] = { 0 };
if (wasm_runtime_lookup_function(module_inst, "main", NULL)
|| wasm_runtime_lookup_function(module_inst,
"__main_argc_argv", NULL)) {
LOG_VERBOSE("Calling main funciton\n");
wasm_application_execute_main(module_inst, app_argc, app_argv);
}
else if ((func = wasm_runtime_lookup_function(module_inst,
"app_main", NULL))) {
exec_env = wasm_runtime_create_exec_env(module_inst,
CONFIG_APP_HEAP_SIZE);
if (!exec_env) {
os_printf("Create exec env failed\n");
return NULL;
}
LOG_VERBOSE("Calling app_main funciton\n");
wasm_runtime_call_wasm(exec_env, func, 0, argv);
if (!wasm_runtime_get_exception(module_inst)) {
os_printf("result: 0x%x\n", argv[0]);
}
wasm_runtime_destroy_exec_env(exec_env);
}
else {
os_printf("Failed to lookup function main or app_main to call\n");
return NULL;
}
wasm_application_execute_main(module_inst, app_argc, app_argv);
if ((exception = wasm_runtime_get_exception(module_inst)))
printf("%s\n", exception);
os_printf("%s\n", exception);
return NULL;
}

47
wamr-compiler/build_llvm_arc.sh Executable file
View File

@ -0,0 +1,47 @@
#!/bin/sh
# Copyright (C) 2020 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
DEPS_DIR=${PWD}/../core/deps
cd ${DEPS_DIR}
if [ ! -d "llvm" ]; then
echo "Clone llvm to core/deps/ .."
git clone https://github.com/llvm/llvm-project.git llvm
fi
cd llvm
mkdir -p build
cd build
if [ ! -f bin/llvm-lto ]; then
CORE_NUM=$(nproc --all)
if [ -z "${CORE_NUM}" ]; then
CORE_NUM=1
fi
echo "Build llvm with" ${CORE_NUM} "cores"
cmake ../llvm \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DCMAKE_BUILD_TYPE:STRING="Release" \
-DLLVM_TARGETS_TO_BUILD:STRING="X86" \
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="ARC" \
-DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \
-DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON \
-DLLVM_ENABLE_ZLIB:BOOL=OFF \
-DLLVM_INCLUDE_DOCS:BOOL=OFF \
-DLLVM_INCLUDE_EXAMPLES:BOOL=OFF \
-DLLVM_INCLUDE_TESTS:BOOL=OFF \
-DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF \
-DLLVM_APPEND_VC_REV:BOOL=OFF
make -j ${CORE_NUM}
else
echo "llvm has already been built"
fi
cd ${PWD}

View File

@ -60,6 +60,8 @@ print_help()
printf(" --disable-aux-stack-check Disable auxiliary stack overflow/underflow check\n");
printf(" --enable-dump-call-stack Enable stack trace feature\n");
printf(" --enable-perf-profiling Enable function performance profiling\n");
printf(" --enable-indirect-mode Enalbe call function through symbol table but not direct call\n");
printf(" --disable-llvm-intrinsics Disable the LLVM built-in intrinsics\n");
printf(" -v=n Set log verbose level (0 to 5, default is 2), larger with more log\n");
printf("Examples: wamrc -o test.aot test.wasm\n");
printf(" wamrc --target=i386 -o test.aot test.wasm\n");
@ -188,6 +190,12 @@ main(int argc, char *argv[])
else if (!strcmp(argv[0], "--enable-perf-profiling")) {
option.enable_aux_stack_frame = true;
}
else if (!strcmp(argv[0], "--enable-indirect-mode")) {
option.is_indirect_mode = true;
}
else if (!strcmp(argv[0], "--disable-llvm-intrinsics")) {
option.disable_llvm_intrinsics = true;
}
else
return print_help();
}